mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-20 03:24:55 +00:00
Merge branch 'develop' of github.com:sleuthkit/autopsy into cl_reports
This commit is contained in:
commit
a8a2e13731
2
.gitignore
vendored
2
.gitignore
vendored
@ -82,6 +82,8 @@ hs_err_pid*.log
|
||||
/RecentActivity/release/
|
||||
/CentralRepository/release/
|
||||
|
||||
/.idea/
|
||||
|
||||
*.img
|
||||
*.vhd
|
||||
*.E01
|
||||
|
@ -109,27 +109,27 @@
|
||||
|
||||
<target name="getTestDataFiles">
|
||||
<mkdir dir="${basedir}/test/qa-functional/data"/>
|
||||
<get src="https://drive.google.com/uc?id=1FkinvA7EFqP4nOSOyTAOli5KefM67ufA" dest="${test-input}/EmbeddedIM_img1_v2.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1zPlIn1xmOeC1VYKmV3fJHl5qE6E_M7K-" dest="${test-input}/BitlockerDetection_img1_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1brQqmX8MJnBPUFEbsdUvZ1X81PmQNVCY" dest="${test-input}/SqlCipherDetection_img1_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=0BxdBkzm5VKGNT0dGY0dqcHVsU3M" dest="${test-input}/IngestFilters_img1_v1.img" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1bghoSm7z7nhmGIxlllyY1MMlbLntxm7n" dest="${test-input}/IngestFilters_local1_v1.zip" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1Ovyv_xVty8xMYgsc3C45pvphfhbdKg1x" dest="${test-input}/PasswordDetection_img1_v1.img" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1HD8s4rculgHV1qZT5g80Kg7j4m1qccrN" dest="${test-input}/VeracryptDetection_img1_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1mr9waEDG5H8GBBn_yXwMUQ6senwC1goL" dest="${test-input}/CommonFiles_img1_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1-vmbmAAb2HBLbf58GpAA97ozGUFiYHbN" dest="${test-input}/CommonFiles_img2_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1ghDjm0NhI3ShMQ38E-4o7XrGeexpjdJb" dest="${test-input}/CommonFiles_img3_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1SJYJFjiumKEtQmeMPsQ6G3xmABarbKm_" dest="${test-input}/CommonFiles_img4_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1HwpDlMa1J7h9AmEd1JhLYGnzihslZJUj" dest="${test-input}/c1ds1_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1Z7mWChlLIpIlScD-DVNGFik5A_rnwS_9" dest="${test-input}/c1ds2_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=14ZxYGyng_eKPe2yaiKDkJLoNcKHIHhW5" dest="${test-input}/c2ds1_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1xv3Lz9m2QLq35ofDfHQNe9aHVtVzHUsj" dest="${test-input}/c2ds2_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1sg-znklB9yJAWq8i1cF2W-QLOM4FjZyv" dest="${test-input}/c3ds1_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1qXyaSlm3hMhv0jl6JkZEficknKjYNOlt" dest="${test-input}/c3ds2_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1gW-SvduRwwoHmOheQypaRZ3ig-bezRre" dest="${test-input}/CommonFilesAttrs_img4_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=14vx83MZcd5PJadOesQz7tja-4a-Hz7eD" dest="${test-input}/CommonFilesAttrs_img3_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1ZIYca4CWxyDcfF5Vf2uWkXeI83mR8L9B" dest="${test-input}/CommonFilesAttrs_img2_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1RvLNhuKzqHURqeVml_o4lpv6jPCJJ9sv" dest="${test-input}/CommonFilesAttrs_img1_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1gyKzqJHtaBjFBqeB29N5vSpf1oH9N0bV" dest="${test-input}/EmbeddedIM_img1_v2.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1gvvV797dKczkwpWII4hIryBXCc0w5zL-" dest="${test-input}/BitlockerDetection_img1_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1lYzd--9YUB7yDccM7NPOo8PC1xxuOiKs" dest="${test-input}/SqlCipherDetection_img1_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1QRNKs824kksiJLZ4qcs59Nytw0fJKEjb" dest="${test-input}/IngestFilters_img1_v1.img" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1OMTB5gD4_VuaFkLWu2I33FN8VAHoRQbW" dest="${test-input}/IngestFilters_local1_v1.zip" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1WGMkivlDi_I_vB1aYY6puAPktbmlNSL-" dest="${test-input}/PasswordDetection_img1_v1.img" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1X2DzJOJ1SjUkAtZXJ3oQHXkjF0NX_jOz" dest="${test-input}/VeracryptDetection_img1_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=19gRepVVvLsDHtBwIkX2VVjsBWIub7aIV" dest="${test-input}/CommonFiles_img1_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1chUMtA0CNyPBZ0yuTl9F_O103R21Ox0p" dest="${test-input}/CommonFiles_img2_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1TmdjSjV7MLwVEmgWGJLOYnWDiZeqOgmd" dest="${test-input}/CommonFiles_img3_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=10u8ocYv6KKDVox6SRv_0fQeVqJjWAFJr" dest="${test-input}/CommonFiles_img4_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1pcYsYB1tTzg63kgTG52u40osbZ-rUHwr" dest="${test-input}/c1ds1_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=11F_Kjht23aFfbdHN1Ryl2fLFv3A76E6O" dest="${test-input}/c1ds2_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1gVnHJEzUmCGVVqhcpI9UHB9zHY2zY5VL" dest="${test-input}/c2ds1_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1RodtAXWXrDvwuMVQYBM_QaOi3XR2B41F" dest="${test-input}/c2ds2_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1t4RKK375nKFAh2iGuu5Nttdy4EFyUqlv" dest="${test-input}/c3ds1_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1be6Szhb57duDkfCc_EGeyHCrAzrIDjs3" dest="${test-input}/c3ds2_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=13YJ6nNXiAxRjNKwzcN9ohwvnVupxPvXc" dest="${test-input}/CommonFilesAttrs_img4_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1UczQeY5ZZiQaql_ErnPRxVyX6qMgbvil" dest="${test-input}/CommonFilesAttrs_img3_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1c2egfrKDQqFD04EqhGIDfs82Uub-fGlx" dest="${test-input}/CommonFilesAttrs_img2_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1ns2olaWsBu_c4EoE4Seh8t_B3U5RnLKd" dest="${test-input}/CommonFilesAttrs_img1_v1.vhd" skipexisting="true"/>
|
||||
|
||||
</target>
|
||||
|
||||
|
@ -45,6 +45,9 @@
|
||||
|
||||
<dependency conf="core->default" org="commons-validator" name="commons-validator" rev="1.6"/>
|
||||
<dependency conf="core->default" org="net.htmlparser.jericho" name="jericho-html" rev="3.3"/>
|
||||
<dependency org="com.squareup.okhttp" name="okhttp" rev="2.7.5"/>
|
||||
<!-- https://mvnrepository.com/artifact/javax.ws.rs/javax.ws.rs-api -->
|
||||
<dependency org="javax.ws.rs" name="javax.ws.rs-api" rev="2.0"/>
|
||||
<override org="jakarta.ws.rs" module="jakarta.ws.rs-api" rev="2.1.5"/>
|
||||
</dependencies>
|
||||
</ivy-module>
|
||||
|
@ -75,7 +75,7 @@ file.reference.javax.ws.rs-api-2.0.1.jar=release/modules/ext/javax.ws.rs-api-2.0
|
||||
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-transports-http-3.0.16.jar=release/modules/ext/cxf-rt-transports-http-3.0.16.jar
|
||||
file.reference.sleuthkit-postgresql-4.6.6.jar=release/modules/ext/sleuthkit-postgresql-4.6.6.jar
|
||||
file.reference.sleuthkit-postgresql-4.6.7.jar=release/modules/ext/sleuthkit-postgresql-4.6.7.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
|
||||
@ -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
|
||||
|
@ -482,8 +482,8 @@
|
||||
<binary-origin>release\modules\ext\jmatio-1.5.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/sleuthkit-postgresql-4.6.6.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/sleuthkit-postgresql-4.6.6.jar</binary-origin>
|
||||
<runtime-relative-path>ext/sleuthkit-postgresql-4.6.7.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/sleuthkit-postgresql-4.6.7.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/tika-parsers-1.20.jar</runtime-relative-path>
|
||||
@ -773,6 +773,14 @@
|
||||
<runtime-relative-path>ext/google-api-services-translate-v2-rev20170525-1.27.0.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/google-api-services-translate-v2-rev20170525-1.27.0.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/okhttp-2.7.5.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/okhttp-2.7.5.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/okio-1.6.0.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/okio-1.6.0.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
</data>
|
||||
</configuration>
|
||||
</project>
|
||||
|
@ -36,10 +36,10 @@ GetTagNameDialog.tagNameExistsTskCore.msg=The {0} tag name already exists in the
|
||||
OpenLogFolder.error1=Log File Not Found: {0}
|
||||
OpenLogFolder.CouldNotOpenLogFolder=Could not open log folder
|
||||
CTL_OpenLogFolder=Open Log Folder
|
||||
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
|
||||
CTL_OpenOutputFolder=Open Case Folder
|
||||
OpenOutputFolder.error1=Case Folder Not Found: {0}
|
||||
OpenOutputFolder.noCaseOpen=No open case, therefore no current case folder available.
|
||||
OpenOutputFolder.CouldNotOpenOutputFolder=Could not open case folder
|
||||
ShowIngestProgressSnapshotAction.actionName.text=Get Ingest Progress Snapshot
|
||||
OpenPythonModulesFolderAction.actionName.text=Python Plugins
|
||||
OpenPythonModulesFolderAction.errorMsg.folderNotFound=Python plugins folder not found: {0}
|
||||
|
@ -79,10 +79,10 @@ GetTagNameDialog.tagNameExistsTskCore.msg=The {0} tag name already exists in the
|
||||
OpenLogFolder.error1=Log File Not Found: {0}
|
||||
OpenLogFolder.CouldNotOpenLogFolder=Could not open log folder
|
||||
CTL_OpenLogFolder=Open Log Folder
|
||||
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
|
||||
CTL_OpenOutputFolder=Open Case Folder
|
||||
OpenOutputFolder.error1=Case Folder Not Found: {0}
|
||||
OpenOutputFolder.noCaseOpen=No open case, therefore no current case folder available.
|
||||
OpenOutputFolder.CouldNotOpenOutputFolder=Could not open case folder
|
||||
# {0} - old tag name
|
||||
# {1} - artifactID
|
||||
ReplaceBlackboardArtifactTagAction.replaceTag.alert=Unable to replace tag {0} for artifact {1}.
|
||||
|
@ -18,7 +18,6 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GridBagConstraints;
|
||||
@ -40,8 +39,9 @@ import javax.swing.SwingUtilities;
|
||||
import org.openide.util.Lookup;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
||||
import org.sleuthkit.autopsy.datasourceprocessors.RawDSProcessor;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.datasourceprocessors.RawDSProcessor;
|
||||
import org.sleuthkit.autopsy.logicalimager.dsp.LogicalImagerDSProcessor;
|
||||
|
||||
/**
|
||||
* Panel which displays the available DataSourceProcessors and allows selection
|
||||
|
@ -238,13 +238,6 @@ OpenMultiUserCasePanel.cancelButton.text=Cancel
|
||||
OpenMultiUserCasePanel.openSingleUserCaseButton.text=Open Single-User Case...
|
||||
OpenMultiUserCasePanel.openSelectedCaseButton.text=Open Selected Case
|
||||
OpenMultiUserCasePanel.searchLabel.text=Select any case and start typing to search by case name
|
||||
LogicalImagerPanel.jLabel1.text=Insert external drive
|
||||
LogicalImagerPanel.scanButton.text=Scan
|
||||
LogicalImagerPanel.jLabel6.text=Or, pick a Logical Imager folder
|
||||
LogicalImagerPanel.browseButton.text=Browse
|
||||
LogicalImagerPanel.topLabel.text=Import Autopsy Imager Results
|
||||
LogicalImagerPanel.selectDriveLabel.text=Select Drive
|
||||
LogicalImagerPanel.messageLabel.text=Error/Status message
|
||||
UnpackagePortableCaseDialog.desc2Label.text=Portable Case Report Module.
|
||||
UnpackagePortableCaseDialog.desc1Label.text=Unpackage a portable case so it can be opened in Autopsy. Portable cases are created through the
|
||||
UnpackagePortableCaseDialog.exitButton.text=Exit
|
||||
@ -259,4 +252,4 @@ UnpackagePortableCaseProgressDialog.cancelButton.text=Cancel
|
||||
UnpackagePortableCaseProgressDialog.okButton.text=OK
|
||||
UnpackagePortableCaseProgressDialog.resultLabel.text=resultLabel
|
||||
UnpackagePortableCaseDialog.extractLabel.text=Folder to extract to:
|
||||
UnpackagePortableCaseDialog.caseLabel.text=Portable Case:
|
||||
UnpackagePortableCaseDialog.caseLabel.text=Portable Case:
|
||||
|
@ -1,19 +1,5 @@
|
||||
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}
|
||||
Case.creationException.couldNotAcquireDirLock=Failed to get lock on case directory
|
||||
@ -182,27 +168,6 @@ LogicalEvidenceFilePanel.pathValidation.getOpenCase.Error=Warning: Exception whi
|
||||
LogicalEvidenceFilePanel.validatePanel.nonL01Error.text=Only files with the .l01 file extension are supported here.
|
||||
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
|
||||
LogicalImagerPanel.messageLabel.noImageSelected=No image selected
|
||||
LogicalImagerPanel.messageLabel.scanningExternalDrives=Scanning external drives for sparse_image.vhd ...
|
||||
LogicalImagerPanel.messageLabel.selectedImage=Selected folder
|
||||
LogicalImagerPanel.selectAcquisitionFromDriveLabel.text=Select acquisition from Drive
|
||||
Menu/Case/OpenRecentCase=Open Recent Case
|
||||
CTL_CaseDeleteAction=Delete Case
|
||||
OpenIDE-Module-Name=Case
|
||||
@ -475,13 +440,6 @@ OpenMultiUserCasePanel.cancelButton.text=Cancel
|
||||
OpenMultiUserCasePanel.openSingleUserCaseButton.text=Open Single-User Case...
|
||||
OpenMultiUserCasePanel.openSelectedCaseButton.text=Open Selected Case
|
||||
OpenMultiUserCasePanel.searchLabel.text=Select any case and start typing to search by case name
|
||||
LogicalImagerPanel.jLabel1.text=Insert external drive
|
||||
LogicalImagerPanel.scanButton.text=Scan
|
||||
LogicalImagerPanel.jLabel6.text=Or, pick a Logical Imager folder
|
||||
LogicalImagerPanel.browseButton.text=Browse
|
||||
LogicalImagerPanel.topLabel.text=Import Autopsy Imager Results
|
||||
LogicalImagerPanel.selectDriveLabel.text=Select Drive
|
||||
LogicalImagerPanel.messageLabel.text=Error/Status message
|
||||
UnpackagePortableCaseDialog.desc2Label.text=Portable Case Report Module.
|
||||
UnpackagePortableCaseDialog.desc1Label.text=Unpackage a portable case so it can be opened in Autopsy. Portable cases are created through the
|
||||
UnpackagePortableCaseDialog.exitButton.text=Exit
|
||||
|
@ -1,236 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.6" maxVersion="1.8" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<Properties>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[0, 65]"/>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[403, 65]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace min="-2" pref="238" max="-2" attributes="0"/>
|
||||
<Component id="topLabel" min="-2" pref="163" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="28" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="messageLabel" alignment="1" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="1" max="-2" attributes="0">
|
||||
<Component id="jSeparator1" alignment="0" max="32767" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="selectDriveLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="289" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Component id="scanButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="126" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="36" max="-2" attributes="0"/>
|
||||
<Component id="browseButton" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="driveListScrollPane" min="-2" pref="211" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="28" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="selectAcquisitionFromDriveLabel" min="-2" pref="305" max="-2" attributes="0"/>
|
||||
<Component id="imageScrollPane" min="-2" pref="346" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="346" max="-2" attributes="0"/>
|
||||
<Component id="jLabel6" min="-2" pref="154" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="144" max="-2" attributes="0"/>
|
||||
<Component id="jLabel1" min="-2" pref="116" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace pref="48" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="topLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jLabel6" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="scanButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="browseButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="jSeparator1" min="-2" pref="4" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="selectDriveLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="selectAcquisitionFromDriveLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="imageScrollPane" pref="0" max="32767" attributes="0"/>
|
||||
<Component id="driveListScrollPane" pref="194" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="26" max="-2" attributes="0"/>
|
||||
<Component id="messageLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="154" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="topLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LogicalImagerPanel.topLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="jLabel1">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LogicalImagerPanel.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="scanButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LogicalImagerPanel.scanButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="scanButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="messageLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LogicalImagerPanel.messageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="selectDriveLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LogicalImagerPanel.selectDriveLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Container class="javax.swing.JScrollPane" name="driveListScrollPane">
|
||||
<AuxValues>
|
||||
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JList" name="driveList">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.editors2.ListModelEditor">
|
||||
<StringArray count="0"/>
|
||||
</Property>
|
||||
<Property name="selectionMode" type="int" value="0"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="driveListMouseClicked"/>
|
||||
<EventHandler event="keyReleased" listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent" handler="driveListKeyReleased"/>
|
||||
</Events>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<String>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JLabel" name="selectAcquisitionFromDriveLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LogicalImagerPanel.selectAcquisitionFromDriveLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="jLabel6">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LogicalImagerPanel.jLabel6.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="browseButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LogicalImagerPanel.browseButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="browseButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Container class="javax.swing.JScrollPane" name="imageScrollPane">
|
||||
<Properties>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[346, 402]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JTable" name="imageTable">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor">
|
||||
<Table columnCount="0" rowCount="0"/>
|
||||
</Property>
|
||||
<Property name="autoResizeMode" type="int" value="0"/>
|
||||
<Property name="columnModel" type="javax.swing.table.TableColumnModel" editor="org.netbeans.modules.form.editors2.TableColumnModelEditor">
|
||||
<TableColumnModel selectionModel="1"/>
|
||||
</Property>
|
||||
<Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor">
|
||||
<JTableSelectionModel selectionMode="0"/>
|
||||
</Property>
|
||||
<Property name="showHorizontalLines" type="boolean" value="false"/>
|
||||
<Property name="showVerticalLines" type="boolean" value="false"/>
|
||||
<Property name="tableHeader" type="javax.swing.table.JTableHeader" editor="org.netbeans.modules.form.editors2.JTableHeaderEditor">
|
||||
<TableHeader reorderingAllowed="false" resizingAllowed="true"/>
|
||||
</Property>
|
||||
<Property name="updateSelectionOnSort" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="imageTableMouseClicked"/>
|
||||
<EventHandler event="keyReleased" listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent" handler="imageTableKeyReleased"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JSeparator" name="jSeparator1">
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
@ -88,7 +88,7 @@ final class NewCaseVisualPanel1 extends JPanel implements DocumentListener {
|
||||
* @return caseName the case name from the case name text field
|
||||
*/
|
||||
String getCaseName() {
|
||||
return this.caseNameTextField.getText();
|
||||
return this.caseNameTextField.getText().trim();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -109,7 +109,7 @@ final class NewCaseVisualPanel1 extends JPanel implements DocumentListener {
|
||||
* @return baseDirectory the base directory from the case dir text field
|
||||
*/
|
||||
String getCaseParentDir() {
|
||||
String parentDir = this.caseParentDirTextField.getText();
|
||||
String parentDir = this.caseParentDirTextField.getText().trim();
|
||||
if (parentDir.endsWith(File.separator) == false) {
|
||||
parentDir = parentDir + File.separator;
|
||||
}
|
||||
|
@ -76,6 +76,7 @@
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="OpenRecentCasePanel.openButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="openButtonActionPerformed"/>
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2018 Basis Technology Corp.
|
||||
* Copyright 2011-2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -24,7 +24,10 @@ import java.io.File;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.windows.WindowManager;
|
||||
@ -51,6 +54,16 @@ class OpenRecentCasePanel extends javax.swing.JPanel {
|
||||
*/
|
||||
private OpenRecentCasePanel() {
|
||||
initComponents();
|
||||
imagesTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
imagesTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
//enable the ok button when something is selected
|
||||
if (!e.getValueIsAdjusting()){
|
||||
openButton.setEnabled(imagesTable.getSelectedRowCount() > 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
@ -90,9 +103,6 @@ class OpenRecentCasePanel extends javax.swing.JPanel {
|
||||
// If there are any images, let's select the first one
|
||||
if (imagesTable.getRowCount() > 0) {
|
||||
imagesTable.setRowSelectionInterval(0, 0);
|
||||
openButton.setEnabled(true);
|
||||
} else {
|
||||
openButton.setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -251,6 +261,7 @@ class OpenRecentCasePanel extends javax.swing.JPanel {
|
||||
cancelButton.setText(org.openide.util.NbBundle.getMessage(OpenRecentCasePanel.class, "OpenRecentCasePanel.cancelButton.text")); // NOI18N
|
||||
|
||||
openButton.setText(org.openide.util.NbBundle.getMessage(OpenRecentCasePanel.class, "OpenRecentCasePanel.openButton.text")); // NOI18N
|
||||
openButton.setEnabled(false);
|
||||
openButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
openButtonActionPerformed(evt);
|
||||
|
@ -351,7 +351,11 @@ class UnpackagePortableCaseDialog extends javax.swing.JDialog {
|
||||
private void unpackageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_unpackageButtonActionPerformed
|
||||
UnpackagePortableCaseProgressDialog dialog = new UnpackagePortableCaseProgressDialog();
|
||||
dialog.unpackageCase(caseTextField.getText(), outputTextField.getText());
|
||||
validatePaths(); // The output folder now exists so we need to disable the unpackage button
|
||||
if (dialog.isSuccess()) {
|
||||
dispose();
|
||||
} else {
|
||||
validatePaths(); // The output folder now exists so we need to disable the unpackage button
|
||||
}
|
||||
}//GEN-LAST:event_unpackageButtonActionPerformed
|
||||
|
||||
|
||||
|
@ -44,11 +44,11 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
class UnpackagePortableCaseProgressDialog extends javax.swing.JDialog implements PropertyChangeListener {
|
||||
|
||||
private UnpackageWorker worker;
|
||||
|
||||
|
||||
/**
|
||||
* Creates new form UnpackagePortableCaseProgressDialog
|
||||
*/
|
||||
@NbBundle.Messages({"UnpackagePortableCaseProgressDialog.title.text=Unpackage Portable Case Progress",})
|
||||
@NbBundle.Messages({"UnpackagePortableCaseProgressDialog.title.text=Unpackage Portable Case Progress",})
|
||||
UnpackagePortableCaseProgressDialog() {
|
||||
super((JFrame) WindowManager.getDefault().getMainWindow(),
|
||||
Bundle.UnpackagePortableCaseProgressDialog_title_text(),
|
||||
@ -56,32 +56,45 @@ class UnpackagePortableCaseProgressDialog extends javax.swing.JDialog implements
|
||||
initComponents();
|
||||
customizeComponents();
|
||||
}
|
||||
|
||||
|
||||
private void customizeComponents() {
|
||||
cancelButton.setEnabled(true);
|
||||
okButton.setEnabled(false);
|
||||
progressBar.setIndeterminate(true);
|
||||
resultLabel.setText(""); // NON-NLS
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unpackage the case
|
||||
*
|
||||
* @param packagedCase The compressed case
|
||||
* @param outputFolder The output folder
|
||||
*
|
||||
* @param packagedCase The compressed case
|
||||
* @param outputFolder The output folder
|
||||
*/
|
||||
void unpackageCase(String packagedCase, String outputFolder) {
|
||||
|
||||
|
||||
worker = new UnpackageWorker(packagedCase, outputFolder);
|
||||
worker.addPropertyChangeListener(this);
|
||||
worker.execute();
|
||||
|
||||
setLocationRelativeTo((JFrame) WindowManager.getDefault().getMainWindow());
|
||||
this.setVisible(true);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@NbBundle.Messages({"UnpackagePortableCaseProgressDialog.propertyChange.success=Successfully unpacked case",})
|
||||
|
||||
/**
|
||||
* Returns whether the unpackaging was completed successfully.
|
||||
*
|
||||
* @return True if unpackaging was completed successfully, false otherwise
|
||||
*/
|
||||
boolean isSuccess() {
|
||||
if (worker == null) {
|
||||
return false;
|
||||
} else {
|
||||
return worker.isSuccess();
|
||||
}
|
||||
}
|
||||
|
||||
@NbBundle.Messages({"UnpackagePortableCaseProgressDialog.propertyChange.success=Successfully unpacked case",})
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
|
||||
@ -92,7 +105,7 @@ class UnpackagePortableCaseProgressDialog extends javax.swing.JDialog implements
|
||||
// Disable cancel button and enable ok
|
||||
cancelButton.setEnabled(false);
|
||||
okButton.setEnabled(true);
|
||||
|
||||
|
||||
if (worker.isSuccess()) {
|
||||
progressBar.setIndeterminate(false);
|
||||
progressBar.setValue(progressBar.getMaximum());
|
||||
@ -106,48 +119,47 @@ class UnpackagePortableCaseProgressDialog extends javax.swing.JDialog implements
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Swing worker to do the decompression.
|
||||
*/
|
||||
private class UnpackageWorker extends SwingWorker<Void, Void> {
|
||||
|
||||
|
||||
private final String packagedCase;
|
||||
private final String outputFolder;
|
||||
|
||||
|
||||
private final AtomicBoolean success = new AtomicBoolean();
|
||||
private String lastError = "";
|
||||
|
||||
|
||||
UnpackageWorker(String packagedCase, String outputFolder) {
|
||||
this.packagedCase = packagedCase;
|
||||
this.outputFolder = outputFolder;
|
||||
this.success.set(false);
|
||||
}
|
||||
|
||||
|
||||
@NbBundle.Messages({
|
||||
"UnpackageWorker.doInBackground.errorFinding7zip=Could not locate 7-Zip executable",
|
||||
"UnpackageWorker.doInBackground.errorCompressingCase=Error unpackaging case",
|
||||
"UnpackageWorker.doInBackground.canceled=Unpackaging canceled by user",
|
||||
})
|
||||
"UnpackageWorker.doInBackground.errorFinding7zip=Could not locate 7-Zip executable",
|
||||
"UnpackageWorker.doInBackground.errorCompressingCase=Error unpackaging case",
|
||||
"UnpackageWorker.doInBackground.canceled=Unpackaging canceled by user",})
|
||||
@Override
|
||||
protected Void doInBackground() throws Exception {
|
||||
|
||||
|
||||
// Find 7-Zip
|
||||
File sevenZipExe = locate7ZipExecutable();
|
||||
if (sevenZipExe == null) {
|
||||
setDisplayError(Bundle.UnpackageWorker_doInBackground_errorFinding7zip());
|
||||
throw new TskCoreException("Error finding 7-Zip executable"); // NON-NLS
|
||||
}
|
||||
|
||||
|
||||
String outputFolderSwitch = "-o" + outputFolder; // NON-NLS
|
||||
ProcessBuilder procBuilder = new ProcessBuilder();
|
||||
procBuilder.command(
|
||||
sevenZipExe.getAbsolutePath(),
|
||||
"x", // Extract
|
||||
"x", // Extract
|
||||
packagedCase,
|
||||
outputFolderSwitch
|
||||
);
|
||||
|
||||
|
||||
try {
|
||||
Process process = procBuilder.start();
|
||||
|
||||
@ -158,7 +170,7 @@ class UnpackagePortableCaseProgressDialog extends javax.swing.JDialog implements
|
||||
}
|
||||
Thread.sleep(200);
|
||||
}
|
||||
|
||||
|
||||
int exitCode = process.exitValue();
|
||||
if (exitCode != 0) {
|
||||
// Save any errors so they can be logged
|
||||
@ -181,63 +193,64 @@ class UnpackagePortableCaseProgressDialog extends javax.swing.JDialog implements
|
||||
success.set(true);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
synchronized protected void done() {
|
||||
if (this.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
get();
|
||||
} catch (Exception ex) {
|
||||
Logger.getLogger(UnpackagePortableCaseProgressDialog.class.getName()).log(Level.SEVERE, "Error unpackaging portable case", ex); // NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Save the error that should be displayed to the user
|
||||
*
|
||||
*
|
||||
* @param errorStr Error to be displayed in the UI
|
||||
*/
|
||||
private synchronized void setDisplayError(String errorStr) {
|
||||
lastError = errorStr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the error to display to the user
|
||||
*
|
||||
* @return Error to be displayed in the UI
|
||||
*/
|
||||
private synchronized String getDisplayError() {
|
||||
return lastError;
|
||||
}
|
||||
|
||||
private boolean isSuccess() {
|
||||
|
||||
protected boolean isSuccess() {
|
||||
return success.get();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Locate the 7-Zip executable from the release folder.
|
||||
*
|
||||
* @return 7-Zip executable
|
||||
*/
|
||||
private File locate7ZipExecutable() {
|
||||
if (!PlatformUtil.isWindowsOS()) {
|
||||
return null;
|
||||
}
|
||||
* Locate the 7-Zip executable from the release folder.
|
||||
*
|
||||
* @return 7-Zip executable
|
||||
*/
|
||||
private File locate7ZipExecutable() {
|
||||
if (!PlatformUtil.isWindowsOS()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String executableToFindName = Paths.get("7-Zip", "7z.exe").toString(); // NON-NLS
|
||||
File exeFile = InstalledFileLocator.getDefault().locate(executableToFindName, UnpackagePortableCaseProgressDialog.class.getPackage().getName(), false);
|
||||
if (null == exeFile) {
|
||||
return null;
|
||||
}
|
||||
String executableToFindName = Paths.get("7-Zip", "7z.exe").toString(); // NON-NLS
|
||||
File exeFile = InstalledFileLocator.getDefault().locate(executableToFindName, UnpackagePortableCaseProgressDialog.class.getPackage().getName(), false);
|
||||
if (null == exeFile) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!exeFile.canExecute()) {
|
||||
return null;
|
||||
}
|
||||
if (!exeFile.canExecute()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return exeFile;
|
||||
}
|
||||
return exeFile;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
|
@ -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<Node> 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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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(),
|
||||
|
@ -754,9 +754,8 @@ public class FileManager implements Closeable {
|
||||
* the parent local directory.
|
||||
* @param localFile The local/logical file or directory.
|
||||
* @param progressUpdater notifier to receive progress notifications on
|
||||
* folders added, or null if not used
|
||||
* @param progressUpdater Called after each file/directory is added to the
|
||||
* case database.
|
||||
* folders added, or null if not used. Called after
|
||||
* each file/directory is added to the case database.
|
||||
*
|
||||
* @return An AbstractFile representation of the local/logical file.
|
||||
*
|
||||
|
@ -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
|
||||
|
@ -0,0 +1,270 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> 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 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 <T> ContentViewerTag<T> 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 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 <T> ContentViewerTag<T> updateTag(ContentViewerTag<T> 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 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 <T> ContentViewerTag<T> getTag(ContentTag contentTag, Class<T> clazz) throws TskCoreException, NoCurrentCaseException {
|
||||
String selectTemplateInstance = String.format(SELECT_TAG_DATA, contentTag.getId());
|
||||
final ResultWrapper<ContentViewerTag<T>> 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 <T>
|
||||
*/
|
||||
private static class ResultWrapper<T> {
|
||||
|
||||
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 <T> void deleteTag(ContentViewerTag<T> 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 <T> Generic class type that will be instantiated and filled in
|
||||
* with data.
|
||||
*/
|
||||
public static class ContentViewerTag<T> {
|
||||
|
||||
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() {
|
||||
}
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
DataContentViewerOtherCases.selectAllMenuItem.text=Select All
|
||||
DataContentViewerOtherCases.showCaseDetailsMenuItem.text=Show Case Details
|
||||
DataContentViewerOtherCases.table.toolTip.text=Click column name to sort. Right-click on the table for more options.
|
||||
DataContentViewerOtherCases.exportToCSVMenuItem.text=Export Selected Rows to CSV
|
||||
DataContentViewerOtherCases.exportToCSVMenuItem.text=Export all Other Occurrences to CSV
|
||||
DataContentViewerOtherCases.showCommonalityMenuItem.text=Show Frequency
|
||||
DataContentViewerOtherCases.earliestCaseDate.text=Earliest Case Date
|
||||
DataContentViewerOtherCases.earliestCaseLabel.toolTipText=
|
||||
|
@ -13,12 +13,11 @@ DataContentViewerOtherCases.dataSources.header.text=Data Source Name
|
||||
DataContentViewerOtherCases.earliestCaseNotAvailable=\ Not Enabled.
|
||||
DataContentViewerOtherCases.foundIn.text=Found %d instances in %d cases and %d data sources.
|
||||
DataContentViewerOtherCases.noOpenCase.errMsg=No open case available.
|
||||
DataContentViewerOtherCases.selectAllMenuItem.text=Select All
|
||||
DataContentViewerOtherCases.showCaseDetailsMenuItem.text=Show Case Details
|
||||
DataContentViewerOtherCases.table.noArtifacts=Item has no attributes with which to search.
|
||||
DataContentViewerOtherCases.table.noResultsFound=No results found.
|
||||
DataContentViewerOtherCases.table.toolTip.text=Click column name to sort. Right-click on the table for more options.
|
||||
DataContentViewerOtherCases.exportToCSVMenuItem.text=Export Selected Rows to CSV
|
||||
DataContentViewerOtherCases.exportToCSVMenuItem.text=Export all Other Occurrences to CSV
|
||||
DataContentViewerOtherCases.showCommonalityMenuItem.text=Show Frequency
|
||||
DataContentViewerOtherCases.earliestCaseDate.text=Earliest Case Date
|
||||
DataContentViewerOtherCases.earliestCaseLabel.toolTipText=
|
||||
|
@ -11,13 +11,6 @@
|
||||
<Property name="useNullLayout" type="boolean" value="true"/>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<MenuItem class="javax.swing.JMenuItem" name="selectAllMenuItem">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle.properties" key="DataContentViewerOtherCases.selectAllMenuItem.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</MenuItem>
|
||||
<MenuItem class="javax.swing.JMenuItem" name="exportToCSVMenuItem">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
@ -46,11 +39,11 @@
|
||||
</NonVisualComponents>
|
||||
<Properties>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[600, 10]"/>
|
||||
<Dimension value="[1000, 10]"/>
|
||||
</Property>
|
||||
<Property name="opaque" type="boolean" value="false"/>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[600, 63]"/>
|
||||
<Dimension value="[1000, 63]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
@ -68,7 +61,7 @@
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="tableContainerPanel" alignment="0" pref="775" max="32767" attributes="0"/>
|
||||
<Component id="tableContainerPanel" alignment="0" pref="1000" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
@ -101,7 +94,7 @@
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="foundInLabel" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="tablesViewerSplitPane" pref="765" max="32767" attributes="0"/>
|
||||
<Component id="tablesViewerSplitPane" pref="990" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
|
@ -89,11 +89,10 @@ import org.sleuthkit.datamodel.TskData;
|
||||
public class DataContentViewerOtherCases extends JPanel implements DataContentViewer {
|
||||
|
||||
private static final long serialVersionUID = -1L;
|
||||
|
||||
private static final String UUID_PLACEHOLDER_STRING = "NoCorrelationAttributeInstance";
|
||||
private static final Logger LOGGER = Logger.getLogger(DataContentViewerOtherCases.class.getName());
|
||||
private static final CorrelationCaseWrapper NO_ARTIFACTS_CASE = new CorrelationCaseWrapper(Bundle.DataContentViewerOtherCases_table_noArtifacts());
|
||||
private static final CorrelationCaseWrapper NO_RESULTS_CASE = new CorrelationCaseWrapper(Bundle.DataContentViewerOtherCases_table_noResultsFound());
|
||||
|
||||
private final OtherOccurrencesFilesTableModel filesTableModel;
|
||||
private final OtherOccurrencesCasesTableModel casesTableModel;
|
||||
private final OtherOccurrencesDataSourcesTableModel dataSourcesTableModel;
|
||||
@ -129,12 +128,20 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a placeholder string to use in place of case uuid when it isn't
|
||||
* available
|
||||
*
|
||||
* @return UUID_PLACEHOLDER_STRING
|
||||
*/
|
||||
static String getPlaceholderUUID() {
|
||||
return UUID_PLACEHOLDER_STRING;
|
||||
}
|
||||
|
||||
private void customizeComponents() {
|
||||
ActionListener actList = (ActionEvent e) -> {
|
||||
JMenuItem jmi = (JMenuItem) e.getSource();
|
||||
if (jmi.equals(selectAllMenuItem)) {
|
||||
filesTable.selectAll();
|
||||
} else if (jmi.equals(showCaseDetailsMenuItem)) {
|
||||
if (jmi.equals(showCaseDetailsMenuItem)) {
|
||||
showCaseDetails(filesTable.getSelectedRow());
|
||||
} else if (jmi.equals(exportToCSVMenuItem)) {
|
||||
try {
|
||||
@ -148,7 +155,6 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
};
|
||||
|
||||
exportToCSVMenuItem.addActionListener(actList);
|
||||
selectAllMenuItem.addActionListener(actList);
|
||||
showCaseDetailsMenuItem.addActionListener(actList);
|
||||
showCommonalityMenuItem.addActionListener(actList);
|
||||
|
||||
@ -804,6 +810,13 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
occurrencePanel.getPreferredSize();
|
||||
detailsPanelScrollPane.setViewportView(occurrencePanel);
|
||||
} else {
|
||||
String currentCaseName;
|
||||
try {
|
||||
currentCaseName = Case.getCurrentCaseThrows().getName();
|
||||
} catch (NoCurrentCaseException ex) {
|
||||
currentCaseName = null;
|
||||
LOGGER.log(Level.WARNING, "Unable to get current case for other occurrences content viewer", ex);
|
||||
}
|
||||
for (CorrelationAttributeInstance corAttr : correlationAttributes) {
|
||||
Map<UniquePathKey, OtherOccurrenceNodeInstanceData> correlatedNodeDataMap = new HashMap<>(0);
|
||||
|
||||
@ -817,7 +830,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
&& casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedRow)).getCaseUUID().equals(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID())) {
|
||||
dataSourcesTableModel.addNodeData(nodeData);
|
||||
}
|
||||
} else {
|
||||
} else if (currentCaseName != null && (casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedRow)).getCaseUUID().equals(currentCaseName))) {
|
||||
dataSourcesTableModel.addNodeData(nodeData);
|
||||
}
|
||||
} catch (EamDbException ex) {
|
||||
@ -837,7 +850,6 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
* selection
|
||||
*/
|
||||
private void updateOnDataSourceSelection() {
|
||||
int[] selectedCaseIndexes = casesTable.getSelectedRows();
|
||||
int[] selectedDataSources = dataSourcesTable.getSelectedRows();
|
||||
filesTableModel.clearTable();
|
||||
for (CorrelationAttributeInstance corAttr : correlationAttributes) {
|
||||
@ -846,23 +858,20 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
// get correlation and reference set instances from DB
|
||||
correlatedNodeDataMap.putAll(getCorrelatedInstances(corAttr, dataSourceName, deviceId));
|
||||
for (OtherOccurrenceNodeInstanceData nodeData : correlatedNodeDataMap.values()) {
|
||||
for (int selectedCaseRow : selectedCaseIndexes) {
|
||||
for (int selectedDataSourceRow : selectedDataSources) {
|
||||
try {
|
||||
if (nodeData.isCentralRepoNode()) {
|
||||
if (casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedCaseRow)) != null
|
||||
&& casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedCaseRow)).getCaseUUID().equals(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID())
|
||||
&& dataSourcesTableModel.getDeviceIdForRow(dataSourcesTable.convertRowIndexToModel(selectedDataSourceRow)).equals(nodeData.getDeviceID())) {
|
||||
filesTableModel.addNodeData(nodeData);
|
||||
}
|
||||
} else {
|
||||
if (dataSourcesTableModel.getDeviceIdForRow(dataSourcesTable.convertRowIndexToModel(selectedDataSourceRow)).equals(nodeData.getDeviceID())) {
|
||||
filesTableModel.addNodeData(nodeData);
|
||||
}
|
||||
for (int selectedDataSourceRow : selectedDataSources) {
|
||||
try {
|
||||
if (nodeData.isCentralRepoNode()) {
|
||||
if (dataSourcesTableModel.getCaseUUIDForRow(dataSourcesTable.convertRowIndexToModel(selectedDataSourceRow)).equals(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID())
|
||||
&& dataSourcesTableModel.getDeviceIdForRow(dataSourcesTable.convertRowIndexToModel(selectedDataSourceRow)).equals(nodeData.getDeviceID())) {
|
||||
filesTableModel.addNodeData(nodeData);
|
||||
}
|
||||
} else {
|
||||
if (dataSourcesTableModel.getDeviceIdForRow(dataSourcesTable.convertRowIndexToModel(selectedDataSourceRow)).equals(nodeData.getDeviceID())) {
|
||||
filesTableModel.addNodeData(nodeData);
|
||||
}
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.WARNING, "Unable to get correlation attribute instance from OtherOccurrenceNodeInstanceData for case " + nodeData.getCaseName(), ex);
|
||||
}
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.WARNING, "Unable to get correlation attribute instance from OtherOccurrenceNodeInstanceData for case " + nodeData.getCaseName(), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -928,7 +937,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
if (EamDb.isEnabled()) {
|
||||
CorrelationCase partialCase;
|
||||
partialCase = casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(caseTableRowIdx));
|
||||
if (partialCase == null){
|
||||
if (partialCase == null) {
|
||||
return "";
|
||||
}
|
||||
return EamDb.getInstance().getCaseByUUID(partialCase.getCaseUUID()).getCreationDate();
|
||||
@ -951,7 +960,6 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
private void initComponents() {
|
||||
|
||||
rightClickPopupMenu = new javax.swing.JPopupMenu();
|
||||
selectAllMenuItem = new javax.swing.JMenuItem();
|
||||
exportToCSVMenuItem = new javax.swing.JMenuItem();
|
||||
showCaseDetailsMenuItem = new javax.swing.JMenuItem();
|
||||
showCommonalityMenuItem = new javax.swing.JMenuItem();
|
||||
@ -981,9 +989,6 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
}
|
||||
});
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(selectAllMenuItem, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.selectAllMenuItem.text")); // NOI18N
|
||||
rightClickPopupMenu.add(selectAllMenuItem);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(exportToCSVMenuItem, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.exportToCSVMenuItem.text")); // NOI18N
|
||||
rightClickPopupMenu.add(exportToCSVMenuItem);
|
||||
|
||||
@ -993,9 +998,9 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
org.openide.awt.Mnemonics.setLocalizedText(showCommonalityMenuItem, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.showCommonalityMenuItem.text")); // NOI18N
|
||||
rightClickPopupMenu.add(showCommonalityMenuItem);
|
||||
|
||||
setMinimumSize(new java.awt.Dimension(600, 10));
|
||||
setMinimumSize(new java.awt.Dimension(1000, 10));
|
||||
setOpaque(false);
|
||||
setPreferredSize(new java.awt.Dimension(600, 63));
|
||||
setPreferredSize(new java.awt.Dimension(1000, 63));
|
||||
|
||||
tableContainerPanel.setPreferredSize(new java.awt.Dimension(600, 63));
|
||||
tableContainerPanel.setRequestFocusEnabled(false);
|
||||
@ -1064,7 +1069,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
.addComponent(earliestCaseDate, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(foundInLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addComponent(tablesViewerSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 765, Short.MAX_VALUE))
|
||||
.addComponent(tablesViewerSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 990, Short.MAX_VALUE))
|
||||
.addContainerGap())
|
||||
);
|
||||
tableContainerPanelLayout.setVerticalGroup(
|
||||
@ -1085,7 +1090,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(tableContainerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 775, Short.MAX_VALUE)
|
||||
.addComponent(tableContainerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 1000, Short.MAX_VALUE)
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
@ -1125,7 +1130,6 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
private javax.swing.JScrollPane filesTableScrollPane;
|
||||
private javax.swing.JLabel foundInLabel;
|
||||
private javax.swing.JPopupMenu rightClickPopupMenu;
|
||||
private javax.swing.JMenuItem selectAllMenuItem;
|
||||
private javax.swing.JMenuItem showCaseDetailsMenuItem;
|
||||
private javax.swing.JMenuItem showCommonalityMenuItem;
|
||||
private javax.swing.JPanel tableContainerPanel;
|
||||
@ -1141,6 +1145,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
private final String dataSourceID;
|
||||
private final String filePath;
|
||||
private final String type;
|
||||
private final String caseUUID;
|
||||
|
||||
UniquePathKey(OtherOccurrenceNodeInstanceData nodeData) {
|
||||
super();
|
||||
@ -1151,6 +1156,20 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
filePath = null;
|
||||
}
|
||||
type = nodeData.getType();
|
||||
String tempCaseUUID;
|
||||
try {
|
||||
tempCaseUUID = nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID();
|
||||
} catch (EamDbException ignored) {
|
||||
//non central repo nodeData won't have a correlation case
|
||||
try {
|
||||
tempCaseUUID = Case.getCurrentCaseThrows().getName();
|
||||
//place holder value will be used since correlation attribute was unavailble
|
||||
} catch (NoCurrentCaseException ex) {
|
||||
LOGGER.log(Level.WARNING, "Unable to get current case", ex);
|
||||
tempCaseUUID = UUID_PLACEHOLDER_STRING;
|
||||
}
|
||||
}
|
||||
caseUUID = tempCaseUUID;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1159,14 +1178,15 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
UniquePathKey otherKey = (UniquePathKey) (other);
|
||||
return (Objects.equals(otherKey.getDataSourceID(), this.getDataSourceID())
|
||||
&& Objects.equals(otherKey.getFilePath(), this.getFilePath())
|
||||
&& Objects.equals(otherKey.getType(), this.getType()));
|
||||
&& Objects.equals(otherKey.getType(), this.getType())
|
||||
&& Objects.equals(otherKey.getCaseUUID(), this.getCaseUUID()));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getDataSourceID(), getFilePath(), getType());
|
||||
return Objects.hash(getDataSourceID(), getFilePath(), getType(), getCaseUUID());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1195,5 +1215,14 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
String getDataSourceID() {
|
||||
return dataSourceID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the case uuid for the UniquePathKey
|
||||
*
|
||||
* @return the case UUID
|
||||
*/
|
||||
String getCaseUUID() {
|
||||
return caseUUID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -175,7 +175,7 @@ final class OccurrencePanel extends javax.swing.JPanel {
|
||||
org.openide.awt.Mnemonics.setLocalizedText(knownStatusLabel, Bundle.OccurrencePanel_commonPropertyKnownStatusLabel_text());
|
||||
addItemToBag(gridY, 0, 0, 0, knownStatusLabel);
|
||||
javax.swing.JLabel knownStatusValue = new javax.swing.JLabel();
|
||||
knownStatusValue.setText(knownStatus.toString());
|
||||
knownStatusValue.setText(knownStatus.getName());
|
||||
if (knownStatus == TskData.FileKnown.BAD) {
|
||||
knownStatusValue.setForeground(Color.RED);
|
||||
}
|
||||
|
@ -21,8 +21,13 @@ package org.sleuthkit.autopsy.centralrepository.contentviewer;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
/**
|
||||
* Model for cells in the data sources section of the other occurrences data
|
||||
@ -31,6 +36,7 @@ import org.openide.util.NbBundle;
|
||||
final class OtherOccurrencesDataSourcesTableModel extends AbstractTableModel {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger logger = Logger.getLogger(OtherOccurrencesDataSourcesTableModel.class.getName());
|
||||
private final Set<DataSourceColumnItem> dataSourceSet = new LinkedHashSet<>();
|
||||
|
||||
/**
|
||||
@ -86,6 +92,25 @@ final class OtherOccurrencesDataSourcesTableModel extends AbstractTableModel {
|
||||
return ((DataSourceColumnItem) dataSourceSet.toArray()[rowIdx]).getDeviceId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the case uuid of the case the data source shown at the specified row
|
||||
* index exists in
|
||||
*
|
||||
* @param rowIdx the row index of the data source you want the case uuid for
|
||||
*
|
||||
* @return the case uuid of the case the specified data source exists in or
|
||||
* an empty string if a device id could not be retrieved
|
||||
*/
|
||||
String getCaseUUIDForRow(int rowIdx) {
|
||||
//if anything would prevent this from working we will return an empty string
|
||||
if (dataSourceSet.isEmpty() || rowIdx < 0
|
||||
|| rowIdx >= dataSourceSet.size()
|
||||
|| !(dataSourceSet.toArray()[rowIdx] instanceof DataSourceColumnItem)) {
|
||||
return "";
|
||||
}
|
||||
return ((DataSourceColumnItem) dataSourceSet.toArray()[rowIdx]).getCaseUUID();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the case name of the data source shown at the specified row index
|
||||
*
|
||||
@ -115,7 +140,21 @@ final class OtherOccurrencesDataSourcesTableModel extends AbstractTableModel {
|
||||
* @param newNodeData data to add to the table
|
||||
*/
|
||||
void addNodeData(OtherOccurrenceNodeData newNodeData) {
|
||||
dataSourceSet.add(new DataSourceColumnItem((OtherOccurrenceNodeInstanceData) newNodeData));
|
||||
OtherOccurrenceNodeInstanceData nodeData = (OtherOccurrenceNodeInstanceData) newNodeData;
|
||||
String caseUUID;
|
||||
try {
|
||||
caseUUID = nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID();
|
||||
} catch (EamDbException ignored) {
|
||||
//non central repo nodeData won't have a correlation case
|
||||
try {
|
||||
caseUUID = Case.getCurrentCaseThrows().getName();
|
||||
//place holder value will be used since correlation attribute was unavailble
|
||||
} catch (NoCurrentCaseException ex) {
|
||||
logger.log(Level.WARNING, "Unable to get current case", ex);
|
||||
caseUUID = DataContentViewerOtherCases.getPlaceholderUUID();
|
||||
}
|
||||
}
|
||||
dataSourceSet.add(new DataSourceColumnItem(nodeData.getCaseName(), nodeData.getDeviceID(), nodeData.getDataSourceName(), caseUUID));
|
||||
fireTableDataChanged();
|
||||
}
|
||||
|
||||
@ -136,30 +175,23 @@ final class OtherOccurrencesDataSourcesTableModel extends AbstractTableModel {
|
||||
private final String caseName;
|
||||
private final String deviceId;
|
||||
private final String dataSourceName;
|
||||
|
||||
/**
|
||||
* Create a DataSourceColumnItem given an
|
||||
* OtherOccurrenceNodeInstanceData object
|
||||
*
|
||||
* @param nodeData the OtherOccurrenceNodeInstanceData which contains
|
||||
* the data source information
|
||||
*/
|
||||
private DataSourceColumnItem(OtherOccurrenceNodeInstanceData nodeData) {
|
||||
this(nodeData.getCaseName(), nodeData.getDeviceID(), nodeData.getDataSourceName());
|
||||
}
|
||||
private final String caseUUID;
|
||||
|
||||
/**
|
||||
* Create a DataSourceColumnItem given a case name, device id, and data
|
||||
* source name
|
||||
*
|
||||
* @param caseName the name of the case the data source exists in
|
||||
* @param deviceId the name of the device id for the data source
|
||||
* @param deviceId the device id for the data source
|
||||
* @param dataSourceName the name of the data source
|
||||
* @param caseUUID the case uuid for the case the data source
|
||||
* exists in
|
||||
*/
|
||||
private DataSourceColumnItem(String caseName, String deviceId, String dataSourceName) {
|
||||
private DataSourceColumnItem(String caseName, String deviceId, String dataSourceName, String caseUUID) {
|
||||
this.caseName = caseName;
|
||||
this.deviceId = deviceId;
|
||||
this.dataSourceName = dataSourceName;
|
||||
this.caseUUID = caseUUID;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -189,17 +221,27 @@ final class OtherOccurrencesDataSourcesTableModel extends AbstractTableModel {
|
||||
return caseName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the case uuid of the case the data source exists in
|
||||
*
|
||||
* @return the case UUID
|
||||
*/
|
||||
private String getCaseUUID() {
|
||||
return caseUUID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
return other instanceof DataSourceColumnItem
|
||||
&& caseName.equals(((DataSourceColumnItem) other).getCaseName())
|
||||
&& dataSourceName.equals(((DataSourceColumnItem) other).getDataSourceName())
|
||||
&& deviceId.equals(((DataSourceColumnItem) other).getDeviceId());
|
||||
&& deviceId.equals(((DataSourceColumnItem) other).getDeviceId())
|
||||
&& caseUUID.equals(((DataSourceColumnItem) other).getCaseUUID());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(caseName, deviceId, dataSourceName);
|
||||
return Objects.hash(caseName, deviceId, dataSourceName, caseUUID);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,9 +22,14 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
/**
|
||||
* Model for cells in the files section of the other occurrences data content
|
||||
@ -33,6 +38,7 @@ import org.apache.commons.io.FilenameUtils;
|
||||
public class OtherOccurrencesFilesTableModel extends AbstractTableModel {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger logger = Logger.getLogger(OtherOccurrencesFilesTableModel.class.getName());
|
||||
private final List<String> nodeKeys = new ArrayList<>();
|
||||
private final Map<String, List<OtherOccurrenceNodeData>> nodeMap = new HashMap<>();
|
||||
|
||||
@ -114,7 +120,20 @@ public class OtherOccurrencesFilesTableModel extends AbstractTableModel {
|
||||
}
|
||||
|
||||
private String createNodeKey(OtherOccurrenceNodeInstanceData nodeData) {
|
||||
return nodeData.getCaseName() + nodeData.getDataSourceName() + nodeData.getDeviceID() + nodeData.getFilePath();
|
||||
String caseUUID;
|
||||
try {
|
||||
caseUUID = nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID();
|
||||
} catch (EamDbException ignored) {
|
||||
//non central repo nodeData won't have a correlation case
|
||||
try {
|
||||
caseUUID = Case.getCurrentCaseThrows().getName();
|
||||
//place holder value will be used since correlation attribute was unavailble
|
||||
} catch (NoCurrentCaseException ex) {
|
||||
logger.log(Level.WARNING, "Unable to get current case", ex);
|
||||
caseUUID = DataContentViewerOtherCases.getPlaceholderUUID();
|
||||
}
|
||||
}
|
||||
return nodeData.getCaseName() + nodeData.getDataSourceName() + nodeData.getDeviceID() + nodeData.getFilePath() + caseUUID;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -123,7 +123,7 @@ final public class CorrelationAttributeNormalizer {
|
||||
|
||||
/**
|
||||
* Verify there are no slashes or invalid domain name characters (such as
|
||||
* '?' or \: ). Normalize to lower case.
|
||||
* '?'). Normalize to lower case.
|
||||
*/
|
||||
private static String normalizeDomain(String data) throws CorrelationAttributeNormalizationException {
|
||||
DomainValidator validator = DomainValidator.getInstance(true);
|
||||
|
@ -29,7 +29,7 @@
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace pref="65" max="32767" attributes="0"/>
|
||||
<EmptySpace pref="47" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -44,7 +44,7 @@
|
||||
<Component id="flagTaggedNotableItemsCheckbox" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="flagPreviouslySeenDevicesCheckbox" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="197" max="32767" attributes="0"/>
|
||||
<EmptySpace pref="47" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
|
@ -88,7 +88,7 @@ final class IngestSettingsPanel extends IngestModuleIngestJobSettingsPanel {
|
||||
.addComponent(flagTaggedNotableItemsCheckbox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(flagPreviouslySeenDevicesCheckbox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(createCorrelationPropertiesCheckbox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
|
||||
.addContainerGap(65, Short.MAX_VALUE))
|
||||
.addContainerGap(47, Short.MAX_VALUE))
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
@ -101,7 +101,7 @@ final class IngestSettingsPanel extends IngestModuleIngestJobSettingsPanel {
|
||||
.addComponent(flagTaggedNotableItemsCheckbox)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(flagPreviouslySeenDevicesCheckbox)
|
||||
.addContainerGap(197, Short.MAX_VALUE))
|
||||
.addContainerGap(47, Short.MAX_VALUE))
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
|
@ -57,7 +57,6 @@ ManageCorrelationPropertiesDialog.cancelButton.text=Cancel
|
||||
ManageCorrelationPropertiesDialog.okButton.text=OK
|
||||
GlobalSettingsPanel.bnManageProperties.text=Manage Correlation Properties
|
||||
EamDbSettingsDialog.lbDatabaseDesc.text=Database File:
|
||||
EamDbSettingsDialog.lbFullDbPath.text=
|
||||
GlobalSettingsPanel.cbUseCentralRepo.text=Use a Central Repository
|
||||
GlobalSettingsPanel.organizationTextArea.text=Organization information can be tracked in the Central Repository.
|
||||
GlobalSettingsPanel.manageOrganizationButton.text=Manage Organizations
|
||||
@ -84,4 +83,4 @@ ManageCasesDialog.orgLabel.text=Organization:
|
||||
ManageCasesDialog.closeButton.text=Close
|
||||
ManageCasesDialog.notesLabel.text=Notes:
|
||||
ManageCasesDialog.dataSourcesLabel.text=Data Sources:
|
||||
ManageCasesDialog.caseInfoLabel.text=Case Info:
|
||||
ManageCasesDialog.caseInfoLabel.text=Case Info:
|
||||
|
@ -115,7 +115,6 @@ ManageCorrelationPropertiesDialog.cancelButton.text=Cancel
|
||||
ManageCorrelationPropertiesDialog.okButton.text=OK
|
||||
GlobalSettingsPanel.bnManageProperties.text=Manage Correlation Properties
|
||||
EamDbSettingsDialog.lbDatabaseDesc.text=Database File:
|
||||
EamDbSettingsDialog.lbFullDbPath.text=
|
||||
GlobalSettingsPanel.cbUseCentralRepo.text=Use a Central Repository
|
||||
GlobalSettingsPanel.organizationTextArea.text=Organization information can be tracked in the Central Repository.
|
||||
GlobalSettingsPanel.manageOrganizationButton.text=Manage Organizations
|
||||
|
@ -9,6 +9,7 @@
|
||||
</NonVisualComponents>
|
||||
<Properties>
|
||||
<Property name="defaultCloseOperation" type="int" value="2"/>
|
||||
<Property name="resizable" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<SyntheticProperties>
|
||||
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
|
||||
@ -35,18 +36,18 @@
|
||||
<Component id="pnButtons" max="32767" attributes="0"/>
|
||||
<Component id="pnSQLiteSettings" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
|
||||
<Component id="pnSQLiteSettings" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="11" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="pnSQLiteSettings" max="32767" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="pnButtons" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -59,9 +60,9 @@
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="bnOk" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="bnOk" linkSize="2" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="11" max="-2" attributes="0"/>
|
||||
<Component id="bnCancel" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="bnCancel" linkSize="2" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
@ -85,6 +86,15 @@
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="EamDbSettingsDialog.bnCancel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[79, 23]"/>
|
||||
</Property>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[79, 23]"/>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[79, 23]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnCancelActionPerformed"/>
|
||||
@ -115,43 +125,37 @@
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="lbHostName" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lbPort" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lbUserName" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lbDatabaseType" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lbDatabasePath" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lbUserName" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lbPort" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" alignment="0" groupAlignment="1" max="-2" attributes="0">
|
||||
<Component id="lbDatabasePath" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="lbDatabaseDesc" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="lbUserPassword" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="lbDatabaseDesc" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="lbFullDbPath" max="32767" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="cbDatabaseType" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="lbSingleUserSqLite" pref="467" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="9" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="tfDatabasePath" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="bnDatabasePathFileOpen" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="tfDatabasePath" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="bnDatabasePathFileOpen" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="11" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Component id="tbDbHostname" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="jpDbPassword" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="tbDbUsername" alignment="1" max="32767" attributes="0"/>
|
||||
<Component id="tbDbPort" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
|
||||
<Component id="cbDatabaseType" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="lbSingleUserSqLite" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="jpDbPassword" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="tbDbUsername" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="tbDbPort" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="tbDbHostname" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="dataBaseFileScrollPane" alignment="0" min="-2" pref="509" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="55" max="-2" attributes="0"/>
|
||||
@ -171,40 +175,42 @@
|
||||
</Group>
|
||||
<Component id="lbDatabaseType" alignment="1" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="lbDatabasePath" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="tfDatabasePath" alignment="3" min="-2" pref="23" max="-2" attributes="0"/>
|
||||
<Component id="tfDatabasePath" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="bnDatabasePathFileOpen" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="tbDbHostname" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lbHostName" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="tbDbPort" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lbPort" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="tbDbUsername" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lbUserName" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jpDbPassword" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lbUserPassword" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="lbFullDbPath" alignment="3" max="32767" attributes="0"/>
|
||||
<Component id="lbDatabaseDesc" alignment="3" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="lbDatabaseDesc" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Component id="filler1" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="dataBaseFileScrollPane" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="filler1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -215,6 +221,9 @@
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="EamDbSettingsDialog.lbDatabasePath.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[80, 14]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="tfDatabasePath">
|
||||
@ -225,6 +234,9 @@
|
||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="EamDbSettingsDialog.tfDatabasePath.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[420, 23]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="bnDatabasePathFileOpen">
|
||||
@ -242,42 +254,77 @@
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="EamDbSettingsDialog.lbHostName.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[80, 14]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="tbDbHostname">
|
||||
<Properties>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[509, 20]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbPort">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="EamDbSettingsDialog.lbPort.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[80, 14]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="tbDbPort">
|
||||
<Properties>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[509, 20]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbUserName">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="EamDbSettingsDialog.lbUserName.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[80, 14]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="tbDbUsername">
|
||||
<Properties>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[509, 20]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbUserPassword">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="EamDbSettingsDialog.lbUserPassword.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[80, 14]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JPasswordField" name="jpDbPassword">
|
||||
<Properties>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[509, 20]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="cbDatabaseType">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||
<Connection code="new javax.swing.DefaultComboBoxModel<>(new EamDbPlatformEnum[]{EamDbPlatformEnum.POSTGRESQL, EamDbPlatformEnum.SQLITE})" type="code"/>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[120, 20]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbDatabaseTypeActionPerformed"/>
|
||||
@ -291,6 +338,9 @@
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="EamDbSettingsDialog.lbSingleUserSqLite.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[381, 14]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbDatabaseType">
|
||||
@ -298,6 +348,15 @@
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="EamDbSettingsDialog.lbDatabaseType.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[80, 14]"/>
|
||||
</Property>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[80, 14]"/>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[80, 14]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbDatabaseDesc">
|
||||
@ -305,12 +364,8 @@
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="EamDbSettingsDialog.lbDatabaseDesc.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbFullDbPath">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="EamDbSettingsDialog.lbFullDbPath.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[80, 14]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
@ -324,6 +379,34 @@
|
||||
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.VerticalGlue"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Container class="javax.swing.JScrollPane" name="dataBaseFileScrollPane">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="null"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JTextArea" name="dataBaseFileTextArea">
|
||||
<Properties>
|
||||
<Property name="editable" type="boolean" value="false"/>
|
||||
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="f0" green="f0" red="f0" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="columns" type="int" value="20"/>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Tahoma" size="11" style="0"/>
|
||||
</Property>
|
||||
<Property name="lineWrap" type="boolean" value="true"/>
|
||||
<Property name="rows" type="int" value="3"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
|
@ -142,12 +142,17 @@ public class EamDbSettingsDialog extends JDialog {
|
||||
lbSingleUserSqLite = new javax.swing.JLabel();
|
||||
lbDatabaseType = new javax.swing.JLabel();
|
||||
lbDatabaseDesc = new javax.swing.JLabel();
|
||||
lbFullDbPath = new javax.swing.JLabel();
|
||||
filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 32767));
|
||||
dataBaseFileScrollPane = new javax.swing.JScrollPane();
|
||||
dataBaseFileTextArea = new javax.swing.JTextArea();
|
||||
|
||||
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
|
||||
setResizable(false);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(bnCancel, org.openide.util.NbBundle.getMessage(EamDbSettingsDialog.class, "EamDbSettingsDialog.bnCancel.text")); // NOI18N
|
||||
bnCancel.setMaximumSize(new java.awt.Dimension(79, 23));
|
||||
bnCancel.setMinimumSize(new java.awt.Dimension(79, 23));
|
||||
bnCancel.setPreferredSize(new java.awt.Dimension(79, 23));
|
||||
bnCancel.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
bnCancelActionPerformed(evt);
|
||||
@ -169,25 +174,30 @@ public class EamDbSettingsDialog extends JDialog {
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(bnOk)
|
||||
.addGap(11, 11, 11)
|
||||
.addComponent(bnCancel)
|
||||
.addComponent(bnCancel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
pnButtonsLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {bnCancel, bnOk});
|
||||
|
||||
pnButtonsLayout.setVerticalGroup(
|
||||
pnButtonsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(pnButtonsLayout.createSequentialGroup()
|
||||
.addGap(0, 0, 0)
|
||||
.addGroup(pnButtonsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(bnOk)
|
||||
.addComponent(bnCancel))
|
||||
.addComponent(bnCancel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGap(0, 0, 0))
|
||||
);
|
||||
|
||||
pnSQLiteSettings.setBorder(javax.swing.BorderFactory.createEtchedBorder());
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(lbDatabasePath, org.openide.util.NbBundle.getMessage(EamDbSettingsDialog.class, "EamDbSettingsDialog.lbDatabasePath.text")); // NOI18N
|
||||
lbDatabasePath.setPreferredSize(new java.awt.Dimension(80, 14));
|
||||
|
||||
tfDatabasePath.setText(org.openide.util.NbBundle.getMessage(EamDbSettingsDialog.class, "EamDbSettingsDialog.tfDatabasePath.text")); // NOI18N
|
||||
tfDatabasePath.setToolTipText(org.openide.util.NbBundle.getMessage(EamDbSettingsDialog.class, "EamDbSettingsDialog.tfDatabasePath.toolTipText")); // NOI18N
|
||||
tfDatabasePath.setPreferredSize(new java.awt.Dimension(420, 23));
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(bnDatabasePathFileOpen, org.openide.util.NbBundle.getMessage(EamDbSettingsDialog.class, "EamDbSettingsDialog.bnDatabasePathFileOpen.text")); // NOI18N
|
||||
bnDatabasePathFileOpen.addActionListener(new java.awt.event.ActionListener() {
|
||||
@ -197,14 +207,27 @@ public class EamDbSettingsDialog extends JDialog {
|
||||
});
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(lbHostName, org.openide.util.NbBundle.getMessage(EamDbSettingsDialog.class, "EamDbSettingsDialog.lbHostName.text")); // NOI18N
|
||||
lbHostName.setPreferredSize(new java.awt.Dimension(80, 14));
|
||||
|
||||
tbDbHostname.setPreferredSize(new java.awt.Dimension(509, 20));
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(lbPort, org.openide.util.NbBundle.getMessage(EamDbSettingsDialog.class, "EamDbSettingsDialog.lbPort.text")); // NOI18N
|
||||
lbPort.setPreferredSize(new java.awt.Dimension(80, 14));
|
||||
|
||||
tbDbPort.setPreferredSize(new java.awt.Dimension(509, 20));
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(lbUserName, org.openide.util.NbBundle.getMessage(EamDbSettingsDialog.class, "EamDbSettingsDialog.lbUserName.text")); // NOI18N
|
||||
lbUserName.setPreferredSize(new java.awt.Dimension(80, 14));
|
||||
|
||||
tbDbUsername.setPreferredSize(new java.awt.Dimension(509, 20));
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(lbUserPassword, org.openide.util.NbBundle.getMessage(EamDbSettingsDialog.class, "EamDbSettingsDialog.lbUserPassword.text")); // NOI18N
|
||||
lbUserPassword.setPreferredSize(new java.awt.Dimension(80, 14));
|
||||
|
||||
jpDbPassword.setPreferredSize(new java.awt.Dimension(509, 20));
|
||||
|
||||
cbDatabaseType.setModel(new javax.swing.DefaultComboBoxModel<>(new EamDbPlatformEnum[]{EamDbPlatformEnum.POSTGRESQL, EamDbPlatformEnum.SQLITE}));
|
||||
cbDatabaseType.setPreferredSize(new java.awt.Dimension(120, 20));
|
||||
cbDatabaseType.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cbDatabaseTypeActionPerformed(evt);
|
||||
@ -212,12 +235,25 @@ public class EamDbSettingsDialog extends JDialog {
|
||||
});
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(lbSingleUserSqLite, org.openide.util.NbBundle.getMessage(EamDbSettingsDialog.class, "EamDbSettingsDialog.lbSingleUserSqLite.text")); // NOI18N
|
||||
lbSingleUserSqLite.setPreferredSize(new java.awt.Dimension(381, 14));
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(lbDatabaseType, org.openide.util.NbBundle.getMessage(EamDbSettingsDialog.class, "EamDbSettingsDialog.lbDatabaseType.text")); // NOI18N
|
||||
lbDatabaseType.setMaximumSize(new java.awt.Dimension(80, 14));
|
||||
lbDatabaseType.setMinimumSize(new java.awt.Dimension(80, 14));
|
||||
lbDatabaseType.setPreferredSize(new java.awt.Dimension(80, 14));
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(lbDatabaseDesc, org.openide.util.NbBundle.getMessage(EamDbSettingsDialog.class, "EamDbSettingsDialog.lbDatabaseDesc.text")); // NOI18N
|
||||
lbDatabaseDesc.setPreferredSize(new java.awt.Dimension(80, 14));
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(lbFullDbPath, org.openide.util.NbBundle.getMessage(EamDbSettingsDialog.class, "EamDbSettingsDialog.lbFullDbPath.text")); // NOI18N
|
||||
dataBaseFileScrollPane.setBorder(null);
|
||||
|
||||
dataBaseFileTextArea.setEditable(false);
|
||||
dataBaseFileTextArea.setBackground(new java.awt.Color(240, 240, 240));
|
||||
dataBaseFileTextArea.setColumns(20);
|
||||
dataBaseFileTextArea.setFont(new java.awt.Font("Tahoma", 0, 11)); // NOI18N
|
||||
dataBaseFileTextArea.setLineWrap(true);
|
||||
dataBaseFileTextArea.setRows(3);
|
||||
dataBaseFileScrollPane.setViewportView(dataBaseFileTextArea);
|
||||
|
||||
javax.swing.GroupLayout pnSQLiteSettingsLayout = new javax.swing.GroupLayout(pnSQLiteSettings);
|
||||
pnSQLiteSettings.setLayout(pnSQLiteSettingsLayout);
|
||||
@ -226,34 +262,30 @@ public class EamDbSettingsDialog extends JDialog {
|
||||
.addGroup(pnSQLiteSettingsLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(pnSQLiteSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(lbHostName)
|
||||
.addComponent(lbPort)
|
||||
.addComponent(lbUserName)
|
||||
.addComponent(lbDatabaseType)
|
||||
.addComponent(lbHostName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(lbDatabaseType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(lbDatabasePath, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(lbUserName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(lbPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGroup(pnSQLiteSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
|
||||
.addComponent(lbDatabasePath, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(lbUserPassword, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addComponent(lbDatabaseDesc))
|
||||
.addComponent(lbDatabaseDesc, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(lbUserPassword, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
|
||||
.addGap(10, 10, 10)
|
||||
.addGroup(pnSQLiteSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(lbFullDbPath, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(pnSQLiteSettingsLayout.createSequentialGroup()
|
||||
.addComponent(tfDatabasePath, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(bnDatabasePathFileOpen))
|
||||
.addGroup(pnSQLiteSettingsLayout.createSequentialGroup()
|
||||
.addComponent(cbDatabaseType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(lbSingleUserSqLite, javax.swing.GroupLayout.DEFAULT_SIZE, 467, Short.MAX_VALUE)
|
||||
.addGap(9, 9, 9))
|
||||
.addGroup(pnSQLiteSettingsLayout.createSequentialGroup()
|
||||
.addComponent(tfDatabasePath)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(bnDatabasePathFileOpen)
|
||||
.addGap(11, 11, 11))
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnSQLiteSettingsLayout.createSequentialGroup()
|
||||
.addGroup(pnSQLiteSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(tbDbHostname, javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jpDbPassword, javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(tbDbUsername)
|
||||
.addComponent(tbDbPort, javax.swing.GroupLayout.Alignment.LEADING))
|
||||
.addGap(10, 10, 10))))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(lbSingleUserSqLite, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addComponent(jpDbPassword, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(tbDbUsername, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(tbDbPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(tbDbHostname, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(dataBaseFileScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 509, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addContainerGap())
|
||||
.addGroup(pnSQLiteSettingsLayout.createSequentialGroup()
|
||||
.addGap(55, 55, 55)
|
||||
.addComponent(filler1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
@ -266,35 +298,36 @@ public class EamDbSettingsDialog extends JDialog {
|
||||
.addGroup(pnSQLiteSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(pnSQLiteSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(cbDatabaseType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(lbSingleUserSqLite))
|
||||
.addComponent(lbDatabaseType, javax.swing.GroupLayout.Alignment.TRAILING))
|
||||
.addComponent(lbSingleUserSqLite, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addComponent(lbDatabaseType, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(pnSQLiteSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(lbDatabasePath)
|
||||
.addComponent(tfDatabasePath, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(lbDatabasePath, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(tfDatabasePath, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(bnDatabasePathFileOpen))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(pnSQLiteSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(tbDbHostname, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(lbHostName))
|
||||
.addComponent(lbHostName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(pnSQLiteSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(tbDbPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(lbPort))
|
||||
.addComponent(lbPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(pnSQLiteSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(tbDbUsername, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(lbUserName))
|
||||
.addComponent(lbUserName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(pnSQLiteSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jpDbPassword, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(lbUserPassword))
|
||||
.addComponent(lbUserPassword, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(pnSQLiteSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(lbFullDbPath, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(lbDatabaseDesc, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(filler1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGroup(pnSQLiteSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(pnSQLiteSettingsLayout.createSequentialGroup()
|
||||
.addComponent(lbDatabaseDesc, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(18, 18, 18)
|
||||
.addComponent(filler1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addComponent(dataBaseFileScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
@ -312,11 +345,11 @@ public class EamDbSettingsDialog extends JDialog {
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(10, 10, 10)
|
||||
.addComponent(pnSQLiteSettings, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 11, Short.MAX_VALUE)
|
||||
.addContainerGap()
|
||||
.addComponent(pnSQLiteSettings, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(pnButtons, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(10, 10, 10))
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
pack();
|
||||
@ -357,6 +390,7 @@ public class EamDbSettingsDialog extends JDialog {
|
||||
}
|
||||
try {
|
||||
tfDatabasePath.setText(databaseFile.getCanonicalPath());
|
||||
tfDatabasePath.setCaretPosition(tfDatabasePath.getText().length());
|
||||
valid();
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to get path of selected database file", ex); // NON-NLS
|
||||
@ -584,14 +618,15 @@ public class EamDbSettingsDialog extends JDialog {
|
||||
}//GEN-LAST:event_cbDatabaseTypeActionPerformed
|
||||
|
||||
private void updateFullDbPath() {
|
||||
lbFullDbPath.setText(tfDatabasePath.getText() + File.separator + CENTRAL_REPO_DB_NAME + CENTRAL_REPO_SQLITE_EXT);
|
||||
dataBaseFileTextArea.setText(tfDatabasePath.getText() + File.separator + CENTRAL_REPO_DB_NAME + CENTRAL_REPO_SQLITE_EXT);
|
||||
dataBaseFileTextArea.setCaretPosition(dataBaseFileTextArea.getText().length());
|
||||
}
|
||||
|
||||
private void displayDatabaseSettings(boolean isPostgres) {
|
||||
lbDatabasePath.setVisible(!isPostgres);
|
||||
tfDatabasePath.setVisible(!isPostgres);
|
||||
lbDatabaseDesc.setVisible(!isPostgres);
|
||||
lbFullDbPath.setVisible(!isPostgres);
|
||||
dataBaseFileTextArea.setVisible(!isPostgres);
|
||||
lbSingleUserSqLite.setVisible(!isPostgres);
|
||||
bnDatabasePathFileOpen.setVisible(!isPostgres);
|
||||
lbHostName.setVisible(isPostgres);
|
||||
@ -855,13 +890,14 @@ public class EamDbSettingsDialog extends JDialog {
|
||||
private javax.swing.ButtonGroup bnGrpDatabasePlatforms;
|
||||
private javax.swing.JButton bnOk;
|
||||
private javax.swing.JComboBox<EamDbPlatformEnum> cbDatabaseType;
|
||||
private javax.swing.JScrollPane dataBaseFileScrollPane;
|
||||
private javax.swing.JTextArea dataBaseFileTextArea;
|
||||
private javax.swing.JFileChooser fcDatabasePath;
|
||||
private javax.swing.Box.Filler filler1;
|
||||
private javax.swing.JPasswordField jpDbPassword;
|
||||
private javax.swing.JLabel lbDatabaseDesc;
|
||||
private javax.swing.JLabel lbDatabasePath;
|
||||
private javax.swing.JLabel lbDatabaseType;
|
||||
private javax.swing.JLabel lbFullDbPath;
|
||||
private javax.swing.JLabel lbHostName;
|
||||
private javax.swing.JLabel lbPort;
|
||||
private javax.swing.JLabel lbSingleUserSqLite;
|
||||
|
@ -7,6 +7,7 @@
|
||||
</NonVisualComponents>
|
||||
<Properties>
|
||||
<Property name="defaultCloseOperation" type="int" value="2"/>
|
||||
<Property name="resizable" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<SyntheticProperties>
|
||||
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
|
||||
@ -49,16 +50,16 @@
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace min="-2" pref="20" max="-2" attributes="0"/>
|
||||
<Component id="taInstructions" min="-2" pref="34" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane1" min="-2" pref="180" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane1" pref="254" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lbWarningMsg" min="-2" pref="25" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="okButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="cancelButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
|
@ -132,6 +132,7 @@ final class ManageCorrelationPropertiesDialog extends javax.swing.JDialog {
|
||||
taInstructions = new javax.swing.JTextArea();
|
||||
|
||||
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
|
||||
setResizable(false);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(okButton, org.openide.util.NbBundle.getMessage(ManageCorrelationPropertiesDialog.class, "ManageCorrelationPropertiesDialog.okButton.text")); // NOI18N
|
||||
okButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
@ -220,14 +221,14 @@ final class ManageCorrelationPropertiesDialog extends javax.swing.JDialog {
|
||||
.addGap(20, 20, 20)
|
||||
.addComponent(taInstructions, javax.swing.GroupLayout.PREFERRED_SIZE, 34, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 180, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 254, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(lbWarningMsg, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(okButton)
|
||||
.addComponent(cancelButton))
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
pack();
|
||||
|
@ -3,7 +3,10 @@
|
||||
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
|
||||
<Properties>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[545, 415]"/>
|
||||
<Dimension value="[600, 450]"/>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[600, 450]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<SyntheticProperties>
|
||||
@ -27,7 +30,7 @@
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
|
||||
<Component id="manageOrganizationsScrollPane" max="32767" attributes="0"/>
|
||||
<Component id="manageOrganizationsScrollPane" pref="603" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -35,7 +38,7 @@
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||
<Component id="manageOrganizationsScrollPane" max="32767" attributes="0"/>
|
||||
<Component id="manageOrganizationsScrollPane" pref="443" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
|
@ -159,7 +159,8 @@ public final class ManageOrganizationsDialog extends JDialog {
|
||||
editButton = new javax.swing.JButton();
|
||||
orgDetailsLabel = new javax.swing.JLabel();
|
||||
|
||||
setMinimumSize(new java.awt.Dimension(545, 415));
|
||||
setMinimumSize(new java.awt.Dimension(600, 450));
|
||||
setPreferredSize(new java.awt.Dimension(600, 450));
|
||||
|
||||
manageOrganizationsScrollPane.setMinimumSize(null);
|
||||
manageOrganizationsScrollPane.setPreferredSize(new java.awt.Dimension(535, 415));
|
||||
@ -331,13 +332,13 @@ public final class ManageOrganizationsDialog extends JDialog {
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addGap(0, 0, 0)
|
||||
.addComponent(manageOrganizationsScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addComponent(manageOrganizationsScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 603, Short.MAX_VALUE))
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addGap(0, 0, 0)
|
||||
.addComponent(manageOrganizationsScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addComponent(manageOrganizationsScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 443, Short.MAX_VALUE))
|
||||
);
|
||||
|
||||
pack();
|
||||
|
@ -123,9 +123,9 @@ public final class InstanceCountNode extends DisplayableItemNode {
|
||||
|
||||
final String NO_DESCR = Bundle.InstanceCountNode_createSheet_noDescription();
|
||||
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.nameColLbl"), NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.nameColLbl"), NO_DESCR, ""));
|
||||
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.score.name"), NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.score.name"), NO_DESCR, ""));
|
||||
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.comment.name"), NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.comment.name"), NO_DESCR, ""));
|
||||
if (UserPreferences.hideCentralRepoCommentsAndOccurrences() == false) {
|
||||
if (UserPreferences.getHideSCOColumns() == false) {
|
||||
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.score.name"), NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.score.name"), NO_DESCR, ""));
|
||||
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.comment.name"), NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.comment.name"), NO_DESCR, ""));
|
||||
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.count.name"), NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.count.name"), NO_DESCR, ""));
|
||||
}
|
||||
sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_instancesColLbl(), Bundle.CommonFilesSearchResultsViewerTable_instancesColLbl(), NO_DESCR, this.getInstanceCount()));
|
||||
|
@ -72,7 +72,7 @@ final class AccountDeviceInstanceNode extends AbstractNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
@NbBundle.Messages(value = {"AccountNode.device=Device", "AccountNode.accountName=Account", "AccountNode.accountType=Type", "AccountNode.messageCount=Messages"})
|
||||
@NbBundle.Messages(value = {"AccountNode.device=Device", "AccountNode.accountName=Account", "AccountNode.accountType=Type", "AccountNode.messageCount=Items"})
|
||||
protected Sheet createSheet() {
|
||||
Sheet sheet = super.createSheet();
|
||||
Sheet.Set properties = sheet.get(Sheet.PROPERTIES);
|
||||
|
@ -54,11 +54,9 @@ final class AccountDeviceInstanceNodeFactory extends ChildFactory<AccountDeviceI
|
||||
final List<AccountDeviceInstance> accountDeviceInstancesWithRelationships =
|
||||
commsManager.getAccountDeviceInstancesWithRelationships(commsFilter);
|
||||
for (AccountDeviceInstance accountDeviceInstance : accountDeviceInstancesWithRelationships) {
|
||||
//Filter out device accounts, in the table.
|
||||
if (Account.Type.DEVICE.equals(accountDeviceInstance.getAccount().getAccountType()) ==false) {
|
||||
long communicationsCount = commsManager.getRelationshipSourcesCount(accountDeviceInstance, commsFilter);
|
||||
accountDeviceInstanceKeys.add(new AccountDeviceInstanceKey(accountDeviceInstance, commsFilter, communicationsCount));
|
||||
}
|
||||
long communicationsCount = commsManager.getRelationshipSourcesCount(accountDeviceInstance, commsFilter);
|
||||
accountDeviceInstanceKeys.add(new AccountDeviceInstanceKey(accountDeviceInstance, commsFilter, communicationsCount));
|
||||
|
||||
}
|
||||
} catch (TskCoreException tskCoreException) {
|
||||
logger.log(Level.SEVERE, "Error getting filtered account device instances", tskCoreException);
|
||||
|
@ -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(),
|
||||
@ -104,7 +108,7 @@ public final class AccountsBrowser extends JPanel implements ExplorerManager.Pro
|
||||
accountDeviceInstances.add(((AccountDeviceInstanceNode) node).getAccountDeviceInstance());
|
||||
filter = ((AccountDeviceInstanceNode)node).getFilter();
|
||||
}
|
||||
relationshipBrowser.setSelectionInfo(new SelectionInfo(accountDeviceInstances, filter));
|
||||
relationshipBrowser.setSelectionInfo(new SelectionInfo(accountDeviceInstances, new HashSet<>(), filter));
|
||||
}
|
||||
});
|
||||
|
||||
@ -118,7 +122,7 @@ public final class AccountsBrowser extends JPanel implements ExplorerManager.Pro
|
||||
|
||||
final int rows = Math.min(100, outline.getRowCount());
|
||||
|
||||
for (int column = 0; column < outline.getModel().getColumnCount(); column++) {
|
||||
for (int column = 0; column < outline.getColumnCount(); column++) {
|
||||
int columnWidthLimit = 500;
|
||||
int columnWidth = 0;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
AccountNode.accountName=Account
|
||||
AccountNode.accountType=Type
|
||||
AccountNode.device=Device
|
||||
AccountNode.messageCount=Messages
|
||||
AccountNode.messageCount=Items
|
||||
applyText=Apply
|
||||
CTL_OpenCVTAction=Communications
|
||||
CVTTopComponent.name=\ Communications Visualization
|
||||
|
@ -11,34 +11,10 @@
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
|
||||
<Component id="filtersPane" min="-2" pref="265" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="browseVisualizeTabPane" pref="786" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
|
||||
<Component id="filtersPane" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="5" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Component id="browseVisualizeTabPane" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JTabbedPane" name="browseVisualizeTabPane">
|
||||
<Properties>
|
||||
@ -51,6 +27,11 @@
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="CVTTopComponent.browseVisualizeTabPane.AccessibleContext.accessibleName" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</AccessibilityProperties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="15" insetsLeft="0" insetsBottom="15" insetsRight="15" anchor="18" weightX="0.75" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
@ -85,11 +66,11 @@
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="org.sleuthkit.autopsy.communications.FiltersPanel" name="filtersPane">
|
||||
<Properties>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[256, 495]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="15" insetsLeft="15" insetsBottom="15" insetsRight="5" anchor="18" weightX="0.25" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -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;
|
||||
@ -67,7 +68,6 @@ public final class CVTTopComponent extends TopComponent {
|
||||
Lookup lookup = ((Lookup.Provider)selectedComponent).getLookup();
|
||||
proxyLookup.setNewLookups(lookup);
|
||||
}
|
||||
filtersPane.setDeviceAccountTypeEnabled(browseVisualizeTabPane.getSelectedIndex() != 0);
|
||||
});
|
||||
|
||||
|
||||
@ -93,39 +93,39 @@ public final class CVTTopComponent extends TopComponent {
|
||||
*/
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//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 = 0.75;
|
||||
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
|
||||
|
||||
gridBagConstraints = new GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.fill = GridBagConstraints.BOTH;
|
||||
gridBagConstraints.anchor = GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 0.25;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
gridBagConstraints.insets = new Insets(15, 15, 15, 5);
|
||||
add(filtersPane, gridBagConstraints);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
|
||||
|
@ -11,493 +11,487 @@
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="18"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,2,-54,0,0,1,-40"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="devicesPane" max="32767" attributes="0"/>
|
||||
<Component id="accountTypesPane" alignment="1" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="filtersTitleLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="applyFiltersButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="refreshButton" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="dateRangePane" alignment="0" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="needsRefreshLabel" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="limitPane" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="filtersTitleLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="applyFiltersButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="refreshButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="needsRefreshLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="4" max="-2" attributes="0"/>
|
||||
<Component id="devicesPane" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="accountTypesPane" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="dateRangePane" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="limitPane" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JButton" name="applyFiltersButton">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/communications/images/tick.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.applyFiltersButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="null"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="filtersTitleLabel">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/communications/images/funnel.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.filtersTitleLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Container class="javax.swing.JPanel" name="accountTypesPane">
|
||||
<Container class="javax.swing.JPanel" name="topPane">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="24" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="accountTypesLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="accountTypeRequiredLabel" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="unCheckAllAccountTypesButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="checkAllAccountTypesButton" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
|
||||
<Component id="accountTypesScrollPane" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="accountTypesLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="accountTypeRequiredLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="accountTypesScrollPane" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="checkAllAccountTypesButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="unCheckAllAccountTypesButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JButton" name="unCheckAllAccountTypesButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.unCheckAllAccountTypesButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="unCheckAllAccountTypesButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="accountTypesLabel">
|
||||
<Component class="javax.swing.JLabel" name="filtersTitleLabel">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/accounts.png"/>
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/communications/images/funnel.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.accountTypesLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.filtersTitleLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="checkAllAccountTypesButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.checkAllAccountTypesButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="checkAllAccountTypesButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Container class="javax.swing.JScrollPane" name="accountTypesScrollPane">
|
||||
<Properties>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[2, 200]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="accountTypeListPane">
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout">
|
||||
<Property name="axis" type="int" value="1"/>
|
||||
</Layout>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JLabel" name="accountTypeRequiredLabel">
|
||||
<Component class="javax.swing.JButton" name="refreshButton">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/error-icon-16.png"/>
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/communications/images/arrow-circle-double-135.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.accountTypeRequiredLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.refreshButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="2" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="12" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="applyFiltersButton">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/communications/images/tick.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.applyFiltersButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="5" anchor="12" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="needsRefreshLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.needsRefreshLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="0" green="0" red="ff" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="horizontalTextPosition" type="int" value="2"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="1" gridWidth="3" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="devicesPane">
|
||||
<Container class="javax.swing.JScrollPane" name="scrollPane">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="null"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="9" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="devicesLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="deviceRequiredLabel" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="unCheckAllDevicesButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="checkAllDevicesButton" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
|
||||
<Component id="devicesScrollPane" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="devicesLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="deviceRequiredLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="devicesScrollPane" pref="94" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="checkAllDevicesButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="unCheckAllDevicesButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="5" pref="5" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JButton" name="unCheckAllDevicesButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.unCheckAllDevicesButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="unCheckAllDevicesButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="devicesLabel">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/image.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.devicesLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="checkAllDevicesButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.checkAllDevicesButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="checkAllDevicesButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Container class="javax.swing.JScrollPane" name="devicesScrollPane">
|
||||
<Properties>
|
||||
<Property name="horizontalScrollBarPolicy" type="int" value="31"/>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[27, 75]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Container class="javax.swing.JPanel" name="mainPanel">
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="devicesListPane">
|
||||
<Properties>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[4, 100]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Container class="javax.swing.JPanel" name="limitPane">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="3" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="15" insetsLeft="0" insetsBottom="15" insetsRight="0" anchor="18" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout">
|
||||
<Property name="axis" type="int" value="1"/>
|
||||
</Layout>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="mostRecentLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.mostRecentLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="9" insetsBottom="0" insetsRight="9" anchor="18" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="limitComboBox">
|
||||
<Properties>
|
||||
<Property name="editable" type="boolean" value="true"/>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
|
||||
<StringArray count="6">
|
||||
<StringItem index="0" value="All"/>
|
||||
<StringItem index="1" value="10000"/>
|
||||
<StringItem index="2" value="5000"/>
|
||||
<StringItem index="3" value="1000"/>
|
||||
<StringItem index="4" value="500"/>
|
||||
<StringItem index="5" value="100"/>
|
||||
</StringArray>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="limitComboBoxActionPerformed"/>
|
||||
</Events>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<String>"/>
|
||||
</AuxValues>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Container class="javax.swing.JPanel" name="limitTitlePanel">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="2" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="9" insetsRight="0" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="limitHeaderLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.limitHeaderLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="limitErrorMsgLabel">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/error-icon-16.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.limitErrorMsgLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="0" green="0" red="ff" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="horizontalTextPosition" type="int" value="10"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="12" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JLabel" name="deviceRequiredLabel">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/error-icon-16.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.deviceRequiredLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="0" green="0" red="ff" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="horizontalTextPosition" type="int" value="2"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="dateRangePane">
|
||||
<Container class="javax.swing.JPanel" name="dateRangePane">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="2" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="15" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="dateRangeLabel" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Component id="endCheckBox" linkSize="1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="12" max="-2" attributes="0"/>
|
||||
<Component id="endDatePicker" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="startCheckBox" linkSize="1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="12" max="-2" attributes="0"/>
|
||||
<Component id="startDatePicker" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="dateRangeLabel" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Component id="endCheckBox" linkSize="1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="12" max="-2" attributes="0"/>
|
||||
<Component id="endDatePicker" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="startCheckBox" linkSize="1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="12" max="-2" attributes="0"/>
|
||||
<Component id="startDatePicker" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="dateRangeLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="startDatePicker" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="startCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="endDatePicker" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="endCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="dateRangeLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="startDatePicker" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="startCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="endDatePicker" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="endCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="com.github.lgooddatepicker.components.DatePicker" name="startDatePicker">
|
||||
<Properties>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="dateRangeLabel">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/calendar.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.dateRangeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="startCheckBox">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.startCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="startCheckBoxStateChanged"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="endCheckBox">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.endCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="endCheckBoxStateChanged"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="com.github.lgooddatepicker.components.DatePicker" name="endDatePicker">
|
||||
<Properties>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JButton" name="refreshButton">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/communications/images/arrow-circle-double-135.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.refreshButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="needsRefreshLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.needsRefreshLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="0" green="0" red="ff" type="rgb"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Container class="javax.swing.JPanel" name="limitPane">
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="com.github.lgooddatepicker.components.DatePicker" name="startDatePicker">
|
||||
<Properties>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="dateRangeLabel">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/calendar.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.dateRangeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="startCheckBox">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.startCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="startCheckBoxStateChanged"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="endCheckBox">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.endCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="endCheckBoxStateChanged"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="com.github.lgooddatepicker.components.DatePicker" name="endDatePicker">
|
||||
<Properties>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="devicesPane">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="100" insetsTop="15" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="limitHeaderLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="limitErrorMsgLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="mostRecentLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="limitComboBox" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="limitHeaderLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="limitErrorMsgLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="mostRecentLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="limitComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="32" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="limitHeaderLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.limitHeaderLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="mostRecentLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.mostRecentLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="limitComboBox">
|
||||
<Properties>
|
||||
<Property name="editable" type="boolean" value="true"/>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
|
||||
<StringArray count="6">
|
||||
<StringItem index="0" value="All"/>
|
||||
<StringItem index="1" value="10000"/>
|
||||
<StringItem index="2" value="5000"/>
|
||||
<StringItem index="3" value="1000"/>
|
||||
<StringItem index="4" value="500"/>
|
||||
<StringItem index="5" value="100"/>
|
||||
</StringArray>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="limitComboBoxActionPerformed"/>
|
||||
</Events>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<String>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="limitErrorMsgLabel">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/error-icon-16.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.limitErrorMsgLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="0" green="0" red="ff" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="horizontalTextPosition" type="int" value="10"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JButton" name="unCheckAllDevicesButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.unCheckAllDevicesButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="unCheckAllDevicesButtonActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="2" gridWidth="2" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="9" insetsLeft="0" insetsBottom="0" insetsRight="9" anchor="12" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="devicesLabel">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/image.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.devicesLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="9" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="checkAllDevicesButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.checkAllDevicesButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="checkAllDevicesButtonActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="2" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="9" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="12" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Container class="javax.swing.JScrollPane" name="devicesScrollPane">
|
||||
<Properties>
|
||||
<Property name="horizontalScrollBarPolicy" type="int" value="31"/>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[27, 75]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="1" gridWidth="3" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="devicesListPane">
|
||||
<Properties>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[4, 100]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout">
|
||||
<Property name="axis" type="int" value="1"/>
|
||||
</Layout>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JLabel" name="deviceRequiredLabel">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/error-icon-16.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.deviceRequiredLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="0" green="0" red="ff" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="horizontalTextPosition" type="int" value="2"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="0" gridWidth="2" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="9" insetsRight="0" anchor="12" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="accountTypesPane">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="1" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="15" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JButton" name="unCheckAllAccountTypesButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.unCheckAllAccountTypesButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="unCheckAllAccountTypesButtonActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="2" gridWidth="2" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="9" insetsLeft="0" insetsBottom="0" insetsRight="9" anchor="12" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="accountTypesLabel">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/accounts.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.accountTypesLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="checkAllAccountTypesButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.checkAllAccountTypesButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="checkAllAccountTypesButtonActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="2" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="9" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="12" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Container class="javax.swing.JScrollPane" name="accountTypesScrollPane">
|
||||
<Properties>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[2, 200]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="1" gridWidth="3" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="9" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="accountTypeListPane">
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout">
|
||||
<Property name="axis" type="int" value="3"/>
|
||||
</Layout>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JLabel" name="accountTypeRequiredLabel">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/error-icon-16.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.accountTypeRequiredLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="0" green="0" red="ff" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="horizontalTextPosition" type="int" value="2"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="0" gridWidth="2" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="12" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
|
@ -53,6 +53,7 @@ import org.sleuthkit.autopsy.core.UserPreferences;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import static org.sleuthkit.autopsy.ingest.IngestManager.IngestJobEvent.COMPLETED;
|
||||
import static org.sleuthkit.autopsy.ingest.IngestManager.IngestModuleEvent.DATA_ADDED;
|
||||
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
|
||||
import org.sleuthkit.datamodel.Account;
|
||||
@ -63,6 +64,7 @@ import org.sleuthkit.datamodel.CommunicationsFilter.AccountTypeFilter;
|
||||
import org.sleuthkit.datamodel.CommunicationsFilter.DateRangeFilter;
|
||||
import org.sleuthkit.datamodel.CommunicationsFilter.DeviceFilter;
|
||||
import org.sleuthkit.datamodel.CommunicationsFilter.MostRecentFilter;
|
||||
import org.sleuthkit.datamodel.CommunicationsManager;
|
||||
import org.sleuthkit.datamodel.DataSource;
|
||||
import static org.sleuthkit.datamodel.Relationship.Type.CALL_LOG;
|
||||
import static org.sleuthkit.datamodel.Relationship.Type.CONTACT;
|
||||
@ -96,9 +98,10 @@ final public class FiltersPanel extends JPanel {
|
||||
* Listens to ingest events to enable refresh button
|
||||
*/
|
||||
private final PropertyChangeListener ingestListener;
|
||||
private final PropertyChangeListener ingestJobListener;
|
||||
|
||||
/**
|
||||
* Flag that indicates the UI is not up-sto-date with respect to the case DB
|
||||
* Flag that indicates the UI is not up-to-date with respect to the case DB
|
||||
* and it should be refreshed (by reapplying the filters).
|
||||
*/
|
||||
private boolean needsRefresh;
|
||||
@ -123,6 +126,11 @@ final public class FiltersPanel extends JPanel {
|
||||
@NbBundle.Messages({"refreshText=Refresh Results", "applyText=Apply"})
|
||||
public FiltersPanel() {
|
||||
initComponents();
|
||||
|
||||
CheckBoxIconPanel panel = createAccoutTypeCheckBoxPanel(Account.Type.DEVICE, true);
|
||||
accountTypeMap.put(Account.Type.DEVICE, panel.getCheckBox());
|
||||
accountTypeListPane.add(panel);
|
||||
|
||||
deviceRequiredLabel.setVisible(false);
|
||||
accountTypeRequiredLabel.setVisible(false);
|
||||
startDatePicker.setDate(LocalDate.now().minusWeeks(3));
|
||||
@ -155,18 +163,30 @@ final public class FiltersPanel extends JPanel {
|
||||
// Indicate that a refresh may be needed, unless the data added is Keyword or Hashset hits
|
||||
ModuleDataEvent eventData = (ModuleDataEvent) pce.getOldValue();
|
||||
if (null != eventData
|
||||
&& eventData.getBlackboardArtifactType().getTypeID() != BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()
|
||||
&& eventData.getBlackboardArtifactType().getTypeID() != BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID()) {
|
||||
updateFilters(false);
|
||||
&& (eventData.getBlackboardArtifactType().getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE.getTypeID()
|
||||
|| eventData.getBlackboardArtifactType().getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT.getTypeID()
|
||||
|| eventData.getBlackboardArtifactType().getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG.getTypeID()
|
||||
|| eventData.getBlackboardArtifactType().getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID()))
|
||||
{
|
||||
updateFilters(true);
|
||||
needsRefresh = true;
|
||||
validateFilters();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.ingestJobListener = pce -> {
|
||||
String eventType = pce.getPropertyName();
|
||||
if (eventType.equals(COMPLETED.toString()) &&
|
||||
updateFilters(true)) {
|
||||
|
||||
needsRefresh = true;
|
||||
validateFilters();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
applyFiltersButton.addActionListener(e -> applyFilters());
|
||||
refreshButton.addActionListener(e -> applyFilters());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -219,19 +239,26 @@ final public class FiltersPanel extends JPanel {
|
||||
/**
|
||||
* Updates the filter widgets to reflect he data sources/types in the case.
|
||||
*/
|
||||
private void updateFilters(boolean initialState) {
|
||||
updateAccountTypeFilter();
|
||||
updateDeviceFilter(initialState);
|
||||
private boolean updateFilters(boolean initialState) {
|
||||
boolean newAccountType = updateAccountTypeFilter(initialState);
|
||||
boolean newDeviceFilter = updateDeviceFilter(initialState);
|
||||
|
||||
// both or either are true, return true;
|
||||
return newAccountType || newDeviceFilter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addNotify() {
|
||||
super.addNotify();
|
||||
IngestManager.getInstance().addIngestModuleEventListener(ingestListener);
|
||||
IngestManager.getInstance().addIngestJobEventListener(ingestJobListener);
|
||||
Case.addEventTypeSubscriber(EnumSet.of(CURRENT_CASE), evt -> {
|
||||
//clear the device filter widget when the case changes.
|
||||
devicesMap.clear();
|
||||
devicesListPane.removeAll();
|
||||
|
||||
accountTypeMap.clear();
|
||||
accountTypeListPane.removeAll();
|
||||
});
|
||||
}
|
||||
|
||||
@ -239,69 +266,109 @@ final public class FiltersPanel extends JPanel {
|
||||
public void removeNotify() {
|
||||
super.removeNotify();
|
||||
IngestManager.getInstance().removeIngestModuleEventListener(ingestListener);
|
||||
IngestManager.getInstance().removeIngestJobEventListener(ingestJobListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the Account Types filter widgets
|
||||
*
|
||||
* @param selected the initial value for the account type checkbox
|
||||
*
|
||||
* @return True, if a new accountType was found
|
||||
*/
|
||||
private void updateAccountTypeFilter() {
|
||||
|
||||
//TODO: something like this commented code could be used to show only
|
||||
//the account types that are found:
|
||||
//final CommunicationsManager communicationsManager = Case.getCurrentOpenCase().getSleuthkitCase().getCommunicationsManager();
|
||||
//List<Account.Type> accountTypesInUse = communicationsManager.getAccountTypesInUse();
|
||||
//accountTypesInUSe.forEach(...)
|
||||
Account.Type.PREDEFINED_ACCOUNT_TYPES.forEach(type -> {
|
||||
if (type.equals(Account.Type.CREDIT_CARD)) {
|
||||
//don't show a check box for credit cards
|
||||
} else {
|
||||
accountTypeMap.computeIfAbsent(type, t -> {
|
||||
|
||||
CheckBoxIconPanel panel = new CheckBoxIconPanel(
|
||||
type.getDisplayName(),
|
||||
new ImageIcon(FiltersPanel.class.getResource(Utils.getIconFilePath(type))));
|
||||
panel.setSelected(true);
|
||||
panel.addItemListener(validationListener);
|
||||
private boolean updateAccountTypeFilter(boolean selected) {
|
||||
boolean newOneFound = false;
|
||||
try {
|
||||
final CommunicationsManager communicationsManager = Case.getCurrentCaseThrows().getSleuthkitCase().getCommunicationsManager();
|
||||
List<Account.Type> accountTypesInUse = communicationsManager.getAccountTypesInUse();
|
||||
|
||||
for (Account.Type type : accountTypesInUse) {
|
||||
|
||||
if (!accountTypeMap.containsKey(type) && !type.equals(Account.Type.CREDIT_CARD)) {
|
||||
CheckBoxIconPanel panel = createAccoutTypeCheckBoxPanel(type, selected);
|
||||
accountTypeMap.put(type, panel.getCheckBox());
|
||||
accountTypeListPane.add(panel);
|
||||
if (t.equals(Account.Type.DEVICE)) {
|
||||
//Deveice type filter is enabled based on whether we are in table or graph view.
|
||||
panel.setEnabled(deviceAccountTypeEnabled);
|
||||
}
|
||||
return panel.getCheckBox();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
newOneFound = true;
|
||||
}
|
||||
}
|
||||
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Unable to update to update Account Types Filter", ex);
|
||||
} catch (NoCurrentCaseException ex) {
|
||||
logger.log(Level.WARNING, "A case is required to update the account types filter.", ex);
|
||||
}
|
||||
|
||||
if (newOneFound) {
|
||||
accountTypeListPane.revalidate();
|
||||
}
|
||||
|
||||
return newOneFound;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to create a new instance of the CheckBoxIconPanel base on
|
||||
* the Account.Type and initalState (check box state).
|
||||
*
|
||||
* @param type Account.Type to display on the panel
|
||||
* @param initalState initial check box state
|
||||
*
|
||||
* @return instance of the CheckBoxIconPanel
|
||||
*/
|
||||
private CheckBoxIconPanel createAccoutTypeCheckBoxPanel(Account.Type type, boolean initalState) {
|
||||
CheckBoxIconPanel panel = new CheckBoxIconPanel(
|
||||
type.getDisplayName(),
|
||||
new ImageIcon(FiltersPanel.class.getResource(Utils.getIconFilePath(type))));
|
||||
|
||||
panel.setSelected(initalState);
|
||||
panel.addItemListener(validationListener);
|
||||
return panel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the devices filter widgets
|
||||
*
|
||||
* @param selected Sets the initial state of device check box
|
||||
*
|
||||
* @return true if a new device was found
|
||||
*/
|
||||
private void updateDeviceFilter(boolean initialState) {
|
||||
private boolean updateDeviceFilter(boolean selected) {
|
||||
boolean newOneFound = false;
|
||||
try {
|
||||
final SleuthkitCase sleuthkitCase = Case.getCurrentCaseThrows().getSleuthkitCase();
|
||||
|
||||
for (DataSource dataSource : sleuthkitCase.getDataSources()) {
|
||||
String dsName = sleuthkitCase.getContentById(dataSource.getId()).getName();
|
||||
//store the device id in the map, but display a datasource name in the UI.
|
||||
devicesMap.computeIfAbsent(dataSource.getDeviceId(), ds -> {
|
||||
final JCheckBox jCheckBox = new JCheckBox(dsName, initialState);
|
||||
jCheckBox.addItemListener(validationListener);
|
||||
devicesListPane.add(jCheckBox);
|
||||
return jCheckBox;
|
||||
});
|
||||
if(devicesMap.containsKey(dataSource.getDeviceId())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final JCheckBox jCheckBox = new JCheckBox(dsName, selected);
|
||||
jCheckBox.addItemListener(validationListener);
|
||||
devicesListPane.add(jCheckBox);
|
||||
devicesMap.put(dataSource.getDeviceId(), jCheckBox);
|
||||
|
||||
newOneFound = true;
|
||||
|
||||
}
|
||||
} catch (NoCurrentCaseException ex) {
|
||||
logger.log(Level.INFO, "Filter update cancelled. Case is closed.");
|
||||
} catch (TskCoreException tskCoreException) {
|
||||
logger.log(Level.SEVERE, "There was a error loading the datasources for the case.", tskCoreException);
|
||||
}
|
||||
|
||||
if(newOneFound) {
|
||||
devicesListPane.revalidate();
|
||||
}
|
||||
|
||||
return newOneFound;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a list of subFilters, set the states of the panel controls
|
||||
* accordingly.
|
||||
*
|
||||
* @param subFilters A list of subFilters
|
||||
* @param commFilter Contains a list of subFilters
|
||||
*/
|
||||
public void setFilters(CommunicationsFilter commFilter) {
|
||||
List<CommunicationsFilter.SubFilter> subFilters = commFilter.getAndFilters();
|
||||
@ -317,7 +384,7 @@ final public class FiltersPanel extends JPanel {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the state of the device filter checkboxes
|
||||
* Sets the state of the device filter check boxes
|
||||
*
|
||||
* @param deviceFilter Selected devices
|
||||
*/
|
||||
@ -364,6 +431,12 @@ final public class FiltersPanel extends JPanel {
|
||||
endDatePicker.setEnabled(state.isEnabled());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the state of the most recent UI controls based on the current values
|
||||
* in MostRecentFilter.
|
||||
*
|
||||
* @param filter The MostRecentFilter state to be set
|
||||
*/
|
||||
private void setMostRecentFilter(MostRecentFilter filter) {
|
||||
int limit = filter.getLimit();
|
||||
if(limit > 0) {
|
||||
@ -392,135 +465,124 @@ final public class FiltersPanel extends JPanel {
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
java.awt.GridBagConstraints gridBagConstraints;
|
||||
|
||||
applyFiltersButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/tick.png"))); // NOI18N
|
||||
applyFiltersButton.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.applyFiltersButton.text")); // NOI18N
|
||||
applyFiltersButton.setPreferredSize(null);
|
||||
setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
topPane.setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
filtersTitleLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/funnel.png"))); // NOI18N
|
||||
filtersTitleLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.filtersTitleLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
topPane.add(filtersTitleLabel, gridBagConstraints);
|
||||
|
||||
unCheckAllAccountTypesButton.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.unCheckAllAccountTypesButton.text")); // NOI18N
|
||||
unCheckAllAccountTypesButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
refreshButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/arrow-circle-double-135.png"))); // NOI18N
|
||||
refreshButton.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.refreshButton.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 2;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
|
||||
topPane.add(refreshButton, gridBagConstraints);
|
||||
|
||||
applyFiltersButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/tick.png"))); // NOI18N
|
||||
applyFiltersButton.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.applyFiltersButton.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 5);
|
||||
topPane.add(applyFiltersButton, gridBagConstraints);
|
||||
|
||||
needsRefreshLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.needsRefreshLabel.text")); // NOI18N
|
||||
needsRefreshLabel.setForeground(new java.awt.Color(255, 0, 0));
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.gridwidth = 3;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
topPane.add(needsRefreshLabel, gridBagConstraints);
|
||||
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_END;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
add(topPane, gridBagConstraints);
|
||||
|
||||
scrollPane.setBorder(null);
|
||||
|
||||
mainPanel.setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
limitPane.setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
mostRecentLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.mostRecentLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 9, 0, 9);
|
||||
limitPane.add(mostRecentLabel, gridBagConstraints);
|
||||
|
||||
limitComboBox.setEditable(true);
|
||||
limitComboBox.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "All", "10000", "5000", "1000", "500", "100" }));
|
||||
limitComboBox.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
unCheckAllAccountTypesButtonActionPerformed(evt);
|
||||
limitComboBoxActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
limitPane.add(limitComboBox, gridBagConstraints);
|
||||
|
||||
accountTypesLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/accounts.png"))); // NOI18N
|
||||
accountTypesLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.accountTypesLabel.text")); // NOI18N
|
||||
limitTitlePanel.setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
checkAllAccountTypesButton.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.checkAllAccountTypesButton.text")); // NOI18N
|
||||
checkAllAccountTypesButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
checkAllAccountTypesButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
limitHeaderLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.limitHeaderLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
limitTitlePanel.add(limitHeaderLabel, gridBagConstraints);
|
||||
|
||||
accountTypesScrollPane.setPreferredSize(new java.awt.Dimension(2, 200));
|
||||
limitErrorMsgLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/error-icon-16.png"))); // NOI18N
|
||||
limitErrorMsgLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.limitErrorMsgLabel.text")); // NOI18N
|
||||
limitErrorMsgLabel.setForeground(new java.awt.Color(255, 0, 0));
|
||||
limitErrorMsgLabel.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING);
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
|
||||
limitTitlePanel.add(limitErrorMsgLabel, gridBagConstraints);
|
||||
|
||||
accountTypeListPane.setLayout(new javax.swing.BoxLayout(accountTypeListPane, javax.swing.BoxLayout.Y_AXIS));
|
||||
accountTypesScrollPane.setViewportView(accountTypeListPane);
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.gridwidth = 2;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 0, 9, 0);
|
||||
limitPane.add(limitTitlePanel, gridBagConstraints);
|
||||
|
||||
accountTypeRequiredLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/error-icon-16.png"))); // NOI18N
|
||||
accountTypeRequiredLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.accountTypeRequiredLabel.text")); // NOI18N
|
||||
accountTypeRequiredLabel.setForeground(new java.awt.Color(255, 0, 0));
|
||||
accountTypeRequiredLabel.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);
|
||||
|
||||
javax.swing.GroupLayout accountTypesPaneLayout = new javax.swing.GroupLayout(accountTypesPane);
|
||||
accountTypesPane.setLayout(accountTypesPaneLayout);
|
||||
accountTypesPaneLayout.setHorizontalGroup(
|
||||
accountTypesPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, accountTypesPaneLayout.createSequentialGroup()
|
||||
.addGroup(accountTypesPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addGroup(accountTypesPaneLayout.createSequentialGroup()
|
||||
.addComponent(accountTypesLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(accountTypeRequiredLabel))
|
||||
.addGroup(accountTypesPaneLayout.createSequentialGroup()
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(unCheckAllAccountTypesButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(checkAllAccountTypesButton))
|
||||
.addGroup(accountTypesPaneLayout.createSequentialGroup()
|
||||
.addGap(10, 10, 10)
|
||||
.addComponent(accountTypesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
|
||||
.addGap(0, 0, 0))
|
||||
);
|
||||
accountTypesPaneLayout.setVerticalGroup(
|
||||
accountTypesPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(accountTypesPaneLayout.createSequentialGroup()
|
||||
.addGroup(accountTypesPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(accountTypesLabel)
|
||||
.addComponent(accountTypeRequiredLabel))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(accountTypesScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(accountTypesPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(checkAllAccountTypesButton)
|
||||
.addComponent(unCheckAllAccountTypesButton)))
|
||||
);
|
||||
|
||||
unCheckAllDevicesButton.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.unCheckAllDevicesButton.text")); // NOI18N
|
||||
unCheckAllDevicesButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
unCheckAllDevicesButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
devicesLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/image.png"))); // NOI18N
|
||||
devicesLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.devicesLabel.text")); // NOI18N
|
||||
|
||||
checkAllDevicesButton.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.checkAllDevicesButton.text")); // NOI18N
|
||||
checkAllDevicesButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
checkAllDevicesButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
devicesScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
devicesScrollPane.setMinimumSize(new java.awt.Dimension(27, 75));
|
||||
|
||||
devicesListPane.setMinimumSize(new java.awt.Dimension(4, 100));
|
||||
devicesListPane.setLayout(new javax.swing.BoxLayout(devicesListPane, javax.swing.BoxLayout.Y_AXIS));
|
||||
devicesScrollPane.setViewportView(devicesListPane);
|
||||
|
||||
deviceRequiredLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/error-icon-16.png"))); // NOI18N
|
||||
deviceRequiredLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.deviceRequiredLabel.text")); // NOI18N
|
||||
deviceRequiredLabel.setForeground(new java.awt.Color(255, 0, 0));
|
||||
deviceRequiredLabel.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);
|
||||
|
||||
javax.swing.GroupLayout devicesPaneLayout = new javax.swing.GroupLayout(devicesPane);
|
||||
devicesPane.setLayout(devicesPaneLayout);
|
||||
devicesPaneLayout.setHorizontalGroup(
|
||||
devicesPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(devicesPaneLayout.createSequentialGroup()
|
||||
.addComponent(devicesLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(deviceRequiredLabel))
|
||||
.addGroup(devicesPaneLayout.createSequentialGroup()
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(unCheckAllDevicesButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(checkAllDevicesButton))
|
||||
.addGroup(devicesPaneLayout.createSequentialGroup()
|
||||
.addGap(10, 10, 10)
|
||||
.addComponent(devicesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
devicesPaneLayout.setVerticalGroup(
|
||||
devicesPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(devicesPaneLayout.createSequentialGroup()
|
||||
.addGroup(devicesPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(devicesLabel)
|
||||
.addComponent(deviceRequiredLabel))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(devicesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 94, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(devicesPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(checkAllDevicesButton)
|
||||
.addComponent(unCheckAllDevicesButton))
|
||||
.addGap(5, 5, 5))
|
||||
);
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 3;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(15, 0, 15, 0);
|
||||
mainPanel.add(limitPane, gridBagConstraints);
|
||||
|
||||
startDatePicker.setEnabled(false);
|
||||
|
||||
@ -580,97 +642,178 @@ final public class FiltersPanel extends JPanel {
|
||||
.addComponent(endCheckBox)))
|
||||
);
|
||||
|
||||
refreshButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/arrow-circle-double-135.png"))); // NOI18N
|
||||
refreshButton.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.refreshButton.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 2;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(15, 0, 0, 0);
|
||||
mainPanel.add(dateRangePane, gridBagConstraints);
|
||||
|
||||
needsRefreshLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.needsRefreshLabel.text")); // NOI18N
|
||||
needsRefreshLabel.setForeground(new java.awt.Color(255, 0, 0));
|
||||
devicesPane.setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
limitHeaderLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.limitHeaderLabel.text")); // NOI18N
|
||||
|
||||
mostRecentLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.mostRecentLabel.text")); // NOI18N
|
||||
|
||||
limitComboBox.setEditable(true);
|
||||
limitComboBox.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "All", "10000", "5000", "1000", "500", "100" }));
|
||||
limitComboBox.addActionListener(new java.awt.event.ActionListener() {
|
||||
unCheckAllDevicesButton.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.unCheckAllDevicesButton.text")); // NOI18N
|
||||
unCheckAllDevicesButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
limitComboBoxActionPerformed(evt);
|
||||
unCheckAllDevicesButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 2;
|
||||
gridBagConstraints.gridwidth = 2;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(9, 0, 0, 9);
|
||||
devicesPane.add(unCheckAllDevicesButton, gridBagConstraints);
|
||||
|
||||
limitErrorMsgLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/error-icon-16.png"))); // NOI18N
|
||||
limitErrorMsgLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.limitErrorMsgLabel.text")); // NOI18N
|
||||
limitErrorMsgLabel.setForeground(new java.awt.Color(255, 0, 0));
|
||||
limitErrorMsgLabel.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING);
|
||||
devicesLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/image.png"))); // NOI18N
|
||||
devicesLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.devicesLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 0, 9, 0);
|
||||
devicesPane.add(devicesLabel, gridBagConstraints);
|
||||
|
||||
javax.swing.GroupLayout limitPaneLayout = new javax.swing.GroupLayout(limitPane);
|
||||
limitPane.setLayout(limitPaneLayout);
|
||||
limitPaneLayout.setHorizontalGroup(
|
||||
limitPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(limitPaneLayout.createSequentialGroup()
|
||||
.addComponent(limitHeaderLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(limitErrorMsgLabel)
|
||||
.addContainerGap())
|
||||
.addGroup(limitPaneLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(mostRecentLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(limitComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
limitPaneLayout.setVerticalGroup(
|
||||
limitPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(limitPaneLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(limitPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(limitHeaderLabel)
|
||||
.addComponent(limitErrorMsgLabel))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(limitPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(mostRecentLabel)
|
||||
.addComponent(limitComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGap(0, 32, Short.MAX_VALUE))
|
||||
);
|
||||
checkAllDevicesButton.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.checkAllDevicesButton.text")); // NOI18N
|
||||
checkAllDevicesButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
checkAllDevicesButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 2;
|
||||
gridBagConstraints.gridy = 2;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(9, 0, 0, 0);
|
||||
devicesPane.add(checkAllDevicesButton, gridBagConstraints);
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(devicesPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(accountTypesPane, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(filtersTitleLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(applyFiltersButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(refreshButton))
|
||||
.addComponent(dateRangePane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(needsRefreshLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addComponent(limitPane, 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()
|
||||
.addGap(0, 0, 0)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(filtersTitleLabel)
|
||||
.addComponent(applyFiltersButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(refreshButton))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(needsRefreshLabel)
|
||||
.addGap(4, 4, 4)
|
||||
.addComponent(devicesPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(accountTypesPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(dateRangePane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(limitPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
devicesScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
devicesScrollPane.setMinimumSize(new java.awt.Dimension(27, 75));
|
||||
|
||||
devicesListPane.setMinimumSize(new java.awt.Dimension(4, 100));
|
||||
devicesListPane.setLayout(new javax.swing.BoxLayout(devicesListPane, javax.swing.BoxLayout.Y_AXIS));
|
||||
devicesScrollPane.setViewportView(devicesListPane);
|
||||
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.gridwidth = 3;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
devicesPane.add(devicesScrollPane, gridBagConstraints);
|
||||
|
||||
deviceRequiredLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/error-icon-16.png"))); // NOI18N
|
||||
deviceRequiredLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.deviceRequiredLabel.text")); // NOI18N
|
||||
deviceRequiredLabel.setForeground(new java.awt.Color(255, 0, 0));
|
||||
deviceRequiredLabel.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.gridwidth = 2;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 0, 9, 0);
|
||||
devicesPane.add(deviceRequiredLabel, gridBagConstraints);
|
||||
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.ipady = 100;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(15, 0, 0, 0);
|
||||
mainPanel.add(devicesPane, gridBagConstraints);
|
||||
|
||||
accountTypesPane.setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
unCheckAllAccountTypesButton.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.unCheckAllAccountTypesButton.text")); // NOI18N
|
||||
unCheckAllAccountTypesButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
unCheckAllAccountTypesButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 2;
|
||||
gridBagConstraints.gridwidth = 2;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(9, 0, 0, 9);
|
||||
accountTypesPane.add(unCheckAllAccountTypesButton, gridBagConstraints);
|
||||
|
||||
accountTypesLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/accounts.png"))); // NOI18N
|
||||
accountTypesLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.accountTypesLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
accountTypesPane.add(accountTypesLabel, gridBagConstraints);
|
||||
|
||||
checkAllAccountTypesButton.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.checkAllAccountTypesButton.text")); // NOI18N
|
||||
checkAllAccountTypesButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
checkAllAccountTypesButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 2;
|
||||
gridBagConstraints.gridy = 2;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(9, 0, 0, 0);
|
||||
accountTypesPane.add(checkAllAccountTypesButton, gridBagConstraints);
|
||||
|
||||
accountTypesScrollPane.setPreferredSize(new java.awt.Dimension(2, 200));
|
||||
|
||||
accountTypeListPane.setLayout(new javax.swing.BoxLayout(accountTypeListPane, javax.swing.BoxLayout.PAGE_AXIS));
|
||||
accountTypesScrollPane.setViewportView(accountTypeListPane);
|
||||
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.gridwidth = 3;
|
||||
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(9, 0, 0, 0);
|
||||
accountTypesPane.add(accountTypesScrollPane, gridBagConstraints);
|
||||
|
||||
accountTypeRequiredLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/error-icon-16.png"))); // NOI18N
|
||||
accountTypeRequiredLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.accountTypeRequiredLabel.text")); // NOI18N
|
||||
accountTypeRequiredLabel.setForeground(new java.awt.Color(255, 0, 0));
|
||||
accountTypeRequiredLabel.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.gridwidth = 2;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
|
||||
accountTypesPane.add(accountTypeRequiredLabel, gridBagConstraints);
|
||||
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(15, 0, 0, 0);
|
||||
mainPanel.add(accountTypesPane, gridBagConstraints);
|
||||
|
||||
scrollPane.setViewportView(mainPanel);
|
||||
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 1;
|
||||
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(9, 0, 0, 0);
|
||||
add(scrollPane, gridBagConstraints);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
/**
|
||||
@ -738,6 +881,11 @@ final public class FiltersPanel extends JPanel {
|
||||
endCheckBox.isSelected() ? endDatePicker.getDate().atStartOfDay(zone).toEpochSecond() : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a MostRecentFilter that based on the current state of the ui controls.
|
||||
*
|
||||
* @return A new instance of MostRecentFilter
|
||||
*/
|
||||
private MostRecentFilter getMostRecentFilter() {
|
||||
String value = (String)limitComboBox.getSelectedItem();
|
||||
if(value.trim().equalsIgnoreCase("all")){
|
||||
@ -760,21 +908,6 @@ final public class FiltersPanel extends JPanel {
|
||||
return new DateControlState (endDatePicker.getDate(), endCheckBox.isSelected());
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable the device account type filter. The filter should be
|
||||
* disabled for the browse/table mode and enabled for the visualization.
|
||||
*
|
||||
* @param enable True to enable the device account type filter, False to
|
||||
* disable it.
|
||||
*/
|
||||
void setDeviceAccountTypeEnabled(boolean enable) {
|
||||
deviceAccountTypeEnabled = enable;
|
||||
JCheckBox deviceCheckbox = accountTypeMap.get(Account.Type.DEVICE);
|
||||
if (deviceCheckbox != null) {
|
||||
deviceCheckbox.setEnabled(deviceAccountTypeEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the selection state of all the account type check boxes
|
||||
*
|
||||
@ -796,11 +929,11 @@ final public class FiltersPanel extends JPanel {
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method that sets all the checkboxes in the given map to the given
|
||||
* Helper method that sets all the check boxes in the given map to the given
|
||||
* selection state.
|
||||
*
|
||||
* @param map A map from anything to JCheckBoxes.
|
||||
* @param selected The selection state to set all the checkboxes to.
|
||||
* @param selected The selection state to set all the check boxes to.
|
||||
*/
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||
private void setAllSelected(Map<?, JCheckBox> map, boolean selected) {
|
||||
@ -931,11 +1064,15 @@ final public class FiltersPanel extends JPanel {
|
||||
private final javax.swing.JLabel limitErrorMsgLabel = new javax.swing.JLabel();
|
||||
private final javax.swing.JLabel limitHeaderLabel = new javax.swing.JLabel();
|
||||
private final javax.swing.JPanel limitPane = new javax.swing.JPanel();
|
||||
private final javax.swing.JPanel limitTitlePanel = new javax.swing.JPanel();
|
||||
private final javax.swing.JPanel mainPanel = new javax.swing.JPanel();
|
||||
private final javax.swing.JLabel mostRecentLabel = new javax.swing.JLabel();
|
||||
private final javax.swing.JLabel needsRefreshLabel = new javax.swing.JLabel();
|
||||
private final javax.swing.JButton refreshButton = new javax.swing.JButton();
|
||||
private final javax.swing.JScrollPane scrollPane = new javax.swing.JScrollPane();
|
||||
private final javax.swing.JCheckBox startCheckBox = new javax.swing.JCheckBox();
|
||||
private final com.github.lgooddatepicker.components.DatePicker startDatePicker = new com.github.lgooddatepicker.components.DatePicker();
|
||||
private final javax.swing.JPanel topPane = new javax.swing.JPanel();
|
||||
private final javax.swing.JButton unCheckAllAccountTypesButton = new javax.swing.JButton();
|
||||
private final javax.swing.JButton unCheckAllDevicesButton = new javax.swing.JButton();
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
@ -914,23 +914,24 @@ final public class VisualizationPanel extends JPanel {
|
||||
Object[] selectionCells = graph.getSelectionCells();
|
||||
if (selectionCells.length > 0) {
|
||||
mxICell[] selectedCells = Arrays.asList(selectionCells).toArray(new mxCell[selectionCells.length]);
|
||||
HashSet<AccountDeviceInstance> deviceInstances = new HashSet<>();
|
||||
HashSet<AccountDeviceInstance> selectedNodes = new HashSet<>();
|
||||
HashSet<SelectionInfo.GraphEdge> selectedEdges = new HashSet<>();
|
||||
for (mxICell cell : selectedCells) {
|
||||
if (cell.isEdge()) {
|
||||
mxICell source = (mxICell) graph.getModel().getTerminal(cell, true);
|
||||
mxICell target = (mxICell) graph.getModel().getTerminal(cell, false);
|
||||
|
||||
deviceInstances.add(((AccountDeviceInstanceKey) source.getValue()).getAccountDeviceInstance());
|
||||
deviceInstances.add(((AccountDeviceInstanceKey) target.getValue()).getAccountDeviceInstance());
|
||||
selectedEdges.add(new SelectionInfo.GraphEdge(((AccountDeviceInstanceKey) source.getValue()).getAccountDeviceInstance(),
|
||||
((AccountDeviceInstanceKey) target.getValue()).getAccountDeviceInstance()));
|
||||
|
||||
} else if (cell.isVertex()) {
|
||||
deviceInstances.add(((AccountDeviceInstanceKey) cell.getValue()).getAccountDeviceInstance());
|
||||
selectedNodes.add(((AccountDeviceInstanceKey) cell.getValue()).getAccountDeviceInstance());
|
||||
}
|
||||
}
|
||||
|
||||
relationshipBrowser.setSelectionInfo(new SelectionInfo(deviceInstances, currentFilter));
|
||||
relationshipBrowser.setSelectionInfo(new SelectionInfo(selectedNodes, selectedEdges, currentFilter));
|
||||
} else {
|
||||
relationshipBrowser.setSelectionInfo(new SelectionInfo(Collections.EMPTY_SET, currentFilter));
|
||||
relationshipBrowser.setSelectionInfo(new SelectionInfo(new HashSet<>(), new HashSet<>(), currentFilter));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
BIN
Core/src/org/sleuthkit/autopsy/communications/images/nail.png
Executable file
BIN
Core/src/org/sleuthkit/autopsy/communications/images/nail.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 202 B |
BIN
Core/src/org/sleuthkit/autopsy/communications/images/screw.png
Executable file
BIN
Core/src/org/sleuthkit/autopsy/communications/images/screw.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 217 B |
BIN
Core/src/org/sleuthkit/autopsy/communications/images/threaded.png
Executable file
BIN
Core/src/org/sleuthkit/autopsy/communications/images/threaded.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 263 B |
BIN
Core/src/org/sleuthkit/autopsy/communications/images/unthreaded.png
Executable file
BIN
Core/src/org/sleuthkit/autopsy/communications/images/unthreaded.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 199 B |
@ -1,15 +1,21 @@
|
||||
ContactDetailsPane.nameLabel.text=Placeholder
|
||||
SummaryViewer.countsPanel.border.title=Counts
|
||||
SummaryViewer.emailLabel.text=Emails:
|
||||
SummaryViewer.contactsLabel.text=Contacts:
|
||||
SummaryViewer.attachmentsLabel.text=Attachments:
|
||||
SummaryViewer.attachmentsLabel.text=Media Attachments:
|
||||
OutlineViewPanel.messageLabel.text=<Control Disabled>
|
||||
SummaryViewer.messagesDataLabel.text=messages
|
||||
SummaryViewer.callLogsDataLabel.text=callLogs
|
||||
SummaryViewer.contactsDataLabel.text=contacts
|
||||
SummaryViewer.emailDataLabel.text=emails
|
||||
SummaryViewer.attachmentsDataLabel.text=attachments
|
||||
SummaryViewer.messagesLabel.text=Messages:
|
||||
SummaryViewer.callLogsLabel.text=Call Logs:
|
||||
ThreadRootMessagePanel.showAllCheckBox.text=Show All Messages
|
||||
ThreadPane.backButton.text=<---
|
||||
SummaryViewer.caseReferencesPanel.border.title=Other Occurrences
|
||||
SummaryViewer.fileReferencesPanel.border.title=File References in Current Case
|
||||
MessageViewer.threadsLabel.text=Select a Thread to View
|
||||
MessageViewer.threadNameLabel.text=<threadName>
|
||||
MessageViewer.showingMessagesLabel.text=Showing Messages for Thread:
|
||||
MessageViewer.backButton.AccessibleContext.accessibleDescription=
|
||||
MessageViewer.backButton.text=Threads
|
||||
MessageViewer.showAllButton.text=All Messages
|
||||
|
@ -11,7 +11,7 @@ ContactsViewer_columnHeader_Name=Name
|
||||
ContactsViewer_columnHeader_Phone=Phone
|
||||
ContactsViewer_noContacts_message=<No contacts found for selected account>
|
||||
ContactsViewer_tabTitle=Contacts
|
||||
MediaViewer_Name=Media
|
||||
MediaViewer_Name=Media Attachments
|
||||
MessageNode_Node_Property_Attms=Attachments
|
||||
MessageNode_Node_Property_Date=Date
|
||||
MessageNode_Node_Property_From=From
|
||||
@ -20,27 +20,39 @@ MessageNode_Node_Property_To=To
|
||||
MessageNode_Node_Property_Type=Type
|
||||
MessageViewer_columnHeader_Attms=Attachments
|
||||
MessageViewer_columnHeader_Date=Date
|
||||
MessageViewer_columnHeader_EarlyDate=Earliest Message
|
||||
MessageViewer_columnHeader_From=From
|
||||
MessageViewer_columnHeader_Subject=Subject
|
||||
MessageViewer_columnHeader_To=To
|
||||
MessageViewer_no_messages=<No messages found for selected account>
|
||||
MessageViewer_tabTitle=Messages
|
||||
MessageViewer_viewMessage_all=All
|
||||
MessageViewer_viewMessage_calllogs=Call Logs
|
||||
MessageViewer_viewMessage_selected=Selected
|
||||
MessageViewer_viewMessage_unthreaded=Unthreaded
|
||||
SummaryViewer.countsPanel.border.title=Counts
|
||||
SummaryViewer.emailLabel.text=Emails:
|
||||
SummaryViewer.contactsLabel.text=Contacts:
|
||||
SummaryViewer.attachmentsLabel.text=Attachments:
|
||||
SummaryViewer.attachmentsLabel.text=Media Attachments:
|
||||
OutlineViewPanel.messageLabel.text=<Control Disabled>
|
||||
SummaryViewer.messagesDataLabel.text=messages
|
||||
SummaryViewer.callLogsDataLabel.text=callLogs
|
||||
SummaryViewer.contactsDataLabel.text=contacts
|
||||
SummaryViewer.emailDataLabel.text=emails
|
||||
SummaryViewer.attachmentsDataLabel.text=attachments
|
||||
SummaryViewer.messagesLabel.text=Messages:
|
||||
SummaryViewer.callLogsLabel.text=Call Logs:
|
||||
SummaryViewer.caseReferencesPanel.border.title=Other Occurrences
|
||||
SummaryViewer.fileReferencesPanel.border.title=File References in Current Case
|
||||
SummaryViewer_CaseRefNameColumn_Title=Case Name
|
||||
SummaryViewer_CentralRepository_Message=<Enable Central Resposity to see Other Occurrences>
|
||||
SummaryViewer_Creation_Date_Title=Creation Date
|
||||
SummaryViewer_FileRefNameColumn_Title=Path
|
||||
SummaryViewer_TabTitle=Summary
|
||||
SummeryViewer_FileRef_Message=<Select one Accout to see File References>
|
||||
ThreadRootMessagePanel.showAllCheckBox.text=Show All Messages
|
||||
ThreadPane.backButton.text=<---
|
||||
SummaryViewer.caseReferencesPanel.border.title=Other Occurrences
|
||||
SummaryViewer.fileReferencesPanel.border.title=File References in Current Case
|
||||
MessageViewer.threadsLabel.text=Select a Thread to View
|
||||
MessageViewer.threadNameLabel.text=<threadName>
|
||||
MessageViewer.showingMessagesLabel.text=Showing Messages for Thread:
|
||||
MessageViewer.backButton.AccessibleContext.accessibleDescription=
|
||||
MessageViewer.backButton.text=Threads
|
||||
MessageViewer.showAllButton.text=All Messages
|
||||
|
@ -17,34 +17,7 @@
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="propertySheet" max="32767" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="nameLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="nameLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="propertySheet" pref="283" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="nameLabel">
|
||||
<Properties>
|
||||
@ -55,11 +28,21 @@
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="ContactDetailsPane.nameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="16" insetsLeft="15" insetsBottom="15" insetsRight="15" anchor="23" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="org.openide.explorer.propertysheet.PropertySheet" name="propertySheet">
|
||||
<Properties>
|
||||
<Property name="descriptionAreaVisible" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="1" gridWidth="2" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="9" insetsLeft="15" insetsBottom="16" insetsRight="15" anchor="18" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -73,38 +73,36 @@ public final class ContactDetailsPane extends javax.swing.JPanel implements Expl
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
java.awt.GridBagConstraints gridBagConstraints;
|
||||
|
||||
messageContentViewer1 = new org.sleuthkit.autopsy.contentviewers.MessageContentViewer();
|
||||
nameLabel = new javax.swing.JLabel();
|
||||
propertySheet = new org.openide.explorer.propertysheet.PropertySheet();
|
||||
|
||||
setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
nameLabel.setFont(new java.awt.Font("Tahoma", 0, 24)); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(nameLabel, org.openide.util.NbBundle.getMessage(ContactDetailsPane.class, "ContactDetailsPane.nameLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(16, 15, 15, 15);
|
||||
add(nameLabel, gridBagConstraints);
|
||||
|
||||
propertySheet.setDescriptionAreaVisible(false);
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(propertySheet, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(nameLabel)
|
||||
.addGap(0, 0, Short.MAX_VALUE)))
|
||||
.addContainerGap())
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(nameLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(propertySheet, javax.swing.GroupLayout.DEFAULT_SIZE, 283, Short.MAX_VALUE)
|
||||
.addContainerGap())
|
||||
);
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.gridwidth = 2;
|
||||
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(9, 15, 16, 15);
|
||||
add(propertySheet, gridBagConstraints);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
|
||||
|
@ -36,7 +36,7 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
* ChildFactory for ContactNodes.
|
||||
*/
|
||||
final class ContactsChildNodeFactory extends ChildFactory<BlackboardArtifact>{
|
||||
private static final Logger logger = Logger.getLogger(MessagesChildNodeFactory.class.getName());
|
||||
private static final Logger logger = Logger.getLogger(ContactsChildNodeFactory.class.getName());
|
||||
|
||||
private SelectionInfo selectionInfo;
|
||||
|
||||
@ -68,36 +68,28 @@ final class ContactsChildNodeFactory extends ChildFactory<BlackboardArtifact>{
|
||||
*/
|
||||
@Override
|
||||
protected boolean createKeys(List<BlackboardArtifact> list) {
|
||||
CommunicationsManager communicationManager;
|
||||
try {
|
||||
communicationManager = Case.getCurrentCaseThrows().getSleuthkitCase().getCommunicationsManager();
|
||||
} catch (NoCurrentCaseException | TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to get communications manager from case.", ex); //NON-NLS
|
||||
return false;
|
||||
}
|
||||
|
||||
if(selectionInfo == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final Set<Content> relationshipSources;
|
||||
|
||||
try {
|
||||
relationshipSources = communicationManager.getRelationshipSources(selectionInfo.getAccountDevicesInstances(), selectionInfo.getCommunicationsFilter());
|
||||
|
||||
relationshipSources.stream().filter((content) -> (content instanceof BlackboardArtifact)).forEachOrdered((content) -> {
|
||||
|
||||
BlackboardArtifact bba = (BlackboardArtifact) content;
|
||||
BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(bba.getArtifactTypeID());
|
||||
|
||||
if (fromID == TSK_CONTACT) {
|
||||
list.add(bba);
|
||||
}
|
||||
});
|
||||
|
||||
relationshipSources = selectionInfo.getRelationshipSources();
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to get relationship sources.", ex); //NON-NLS
|
||||
logger.log(Level.SEVERE, "Failed to load relationship sources.", ex); //NON-NLS
|
||||
return false;
|
||||
}
|
||||
|
||||
relationshipSources.stream().filter((content) -> (content instanceof BlackboardArtifact)).forEachOrdered((content) -> {
|
||||
|
||||
BlackboardArtifact bba = (BlackboardArtifact) content;
|
||||
BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(bba.getArtifactTypeID());
|
||||
|
||||
if (fromID == TSK_CONTACT) {
|
||||
list.add(bba);
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -11,29 +11,38 @@
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="contactPane" max="32767" attributes="0"/>
|
||||
<Component id="outlineViewPanel" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="outlineViewPanel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="contactPane" pref="332" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="org.sleuthkit.autopsy.communications.relationships.ContactDetailsPane" name="contactPane">
|
||||
</Component>
|
||||
<Component class="org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel" name="outlineViewPanel">
|
||||
</Component>
|
||||
<Container class="javax.swing.JSplitPane" name="splitPane">
|
||||
<Properties>
|
||||
<Property name="orientation" type="int" value="0"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="23" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="org.sleuthkit.autopsy.communications.relationships.ContactDetailsPane" name="contactPane">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||
<JSplitPaneConstraints position="right"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel" name="outlineViewPanel">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||
<JSplitPaneConstraints position="left"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -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")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//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);
|
||||
}// </editor-fold>//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
|
||||
}
|
||||
|
@ -11,58 +11,57 @@
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="thumbnailViewer" alignment="1" max="32767" attributes="0"/>
|
||||
<Component id="contentViewer" alignment="1" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="separator" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="thumbnailViewer" pref="350" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="separator" min="-2" pref="2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="contentViewer" min="-2" pref="450" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="3" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="org.sleuthkit.autopsy.corecomponents.DataResultViewerThumbnail" name="thumbnailViewer">
|
||||
<Container class="javax.swing.JSplitPane" name="splitPane">
|
||||
<Properties>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[350, 102]"/>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[450, 400]"/>
|
||||
</Property>
|
||||
<Property name="orientation" type="int" value="0"/>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new org.sleuthkit.autopsy.corecomponents.DataResultViewerThumbnail(tableEM)"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="org.sleuthkit.autopsy.contentviewers.MessageContentViewer" name="contentViewer">
|
||||
<Properties>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[450, 400]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new MessageDataContent()"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JSeparator" name="separator">
|
||||
</Component>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="org.sleuthkit.autopsy.corecomponents.DataResultViewerThumbnail" name="thumbnailViewer">
|
||||
<Properties>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[350, 102]"/>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[450, 400]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new org.sleuthkit.autopsy.corecomponents.DataResultViewerThumbnail(tableEM)"/>
|
||||
</AuxValues>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||
<JSplitPaneConstraints position="left"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="org.sleuthkit.autopsy.contentviewers.MessageContentViewer" name="contentViewer">
|
||||
<Properties>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[450, 400]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new MessageDataContent()"/>
|
||||
</AuxValues>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||
<JSplitPaneConstraints position="right"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -59,12 +59,17 @@ final class MediaViewer extends JPanel implements RelationshipsViewer, ExplorerM
|
||||
private final ModifiableProxyLookup proxyLookup;
|
||||
|
||||
@Messages({
|
||||
"MediaViewer_Name=Media"
|
||||
"MediaViewer_Name=Media Attachments"
|
||||
})
|
||||
/**
|
||||
* 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();
|
||||
@ -110,26 +113,21 @@ final class MediaViewer extends JPanel implements RelationshipsViewer, ExplorerM
|
||||
|
||||
@Override
|
||||
public void setSelectionInfo(SelectionInfo info) {
|
||||
final Set<Content> relationshipSources;
|
||||
|
||||
CommunicationsManager communicationManager;
|
||||
Set<Content> relationshipSources;
|
||||
Set<BlackboardArtifact> artifactList = new HashSet<>();
|
||||
|
||||
try {
|
||||
communicationManager = Case.getCurrentCaseThrows().getSleuthkitCase().getCommunicationsManager();
|
||||
relationshipSources = communicationManager.getRelationshipSources(info.getAccountDevicesInstances(), info.getCommunicationsFilter());
|
||||
relationshipSources = info.getRelationshipSources();
|
||||
|
||||
relationshipSources.stream().filter((content) -> (content instanceof BlackboardArtifact)).forEachOrdered((content) -> {
|
||||
artifactList.add((BlackboardArtifact) content);
|
||||
});
|
||||
|
||||
} catch (TskCoreException | NoCurrentCaseException ex) {
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Unable to update selection." , ex);
|
||||
}
|
||||
|
||||
if(artifactList.size() == 0) {
|
||||
thumbnailViewer.resetComponent();
|
||||
}
|
||||
thumbnailViewer.resetComponent();
|
||||
|
||||
thumbnailViewer.setNode(new TableFilterNode(new DataResultFilterNode(new AbstractNode(new AttachmentsChildren(artifactList)), tableEM), true, this.getClass().getName()));
|
||||
}
|
||||
@ -190,43 +188,37 @@ final class MediaViewer extends JPanel implements RelationshipsViewer, ExplorerM
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//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);
|
||||
}// </editor-fold>//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
|
||||
|
||||
|
@ -18,16 +18,13 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.communications.relationships;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.TimeZone;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.Action;
|
||||
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;
|
||||
import org.sleuthkit.autopsy.datamodel.NodeProperty;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
@ -40,24 +37,35 @@ 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;
|
||||
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
|
||||
|
||||
/**
|
||||
* Wraps a BlackboardArtifact as an AbstractNode for use in an OutlookView
|
||||
*/
|
||||
final class MessageNode extends BlackboardArtifactNode {
|
||||
class MessageNode extends BlackboardArtifactNode {
|
||||
|
||||
public static final String UNTHREADED_ID = "<UNTHREADED>";
|
||||
public static final String CALL_LOG_ID = "<CALLLOG>";
|
||||
|
||||
private static final Logger logger = Logger.getLogger(MessageNode.class.getName());
|
||||
|
||||
private final String threadID;
|
||||
|
||||
private final Action preferredAction;
|
||||
|
||||
MessageNode(BlackboardArtifact artifact) {
|
||||
MessageNode(BlackboardArtifact artifact, String threadID, Action preferredAction) {
|
||||
super(artifact);
|
||||
|
||||
this.preferredAction = preferredAction;
|
||||
|
||||
final String stripEnd = StringUtils.stripEnd(artifact.getDisplayName(), "s"); // NON-NLS
|
||||
String removeEndIgnoreCase = StringUtils.removeEndIgnoreCase(stripEnd, "message"); // NON-NLS
|
||||
setDisplayName(removeEndIgnoreCase.isEmpty() ? stripEnd : removeEndIgnoreCase);
|
||||
|
||||
this.threadID = threadID;
|
||||
}
|
||||
|
||||
@Messages({
|
||||
@ -72,7 +80,6 @@ final class MessageNode extends BlackboardArtifactNode {
|
||||
@Override
|
||||
protected Sheet createSheet() {
|
||||
Sheet sheet = super.createSheet();
|
||||
List<Tag> tags = getAllTagsFromDatabase();
|
||||
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
|
||||
if (sheetSet == null) {
|
||||
sheetSet = Sheet.createPropertiesSet();
|
||||
@ -80,19 +87,15 @@ 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();
|
||||
if (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG.getTypeID()) {
|
||||
sheetSet.put(new NodeProperty<>("ThreadID", "ThreadID","",CALL_LOG_ID)); //NON-NLS
|
||||
} else {
|
||||
sheetSet.put(new NodeProperty<>("ThreadID", "ThreadID","",threadID == null ? UNTHREADED_ID : threadID)); //NON-NLS
|
||||
}
|
||||
|
||||
BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(artifact.getArtifactTypeID());
|
||||
if (null != fromID) {
|
||||
@ -183,4 +186,13 @@ final class MessageNode extends BlackboardArtifactNode {
|
||||
public String getSourceName() {
|
||||
return getDisplayName();
|
||||
}
|
||||
|
||||
String getThreadID() {
|
||||
return threadID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Action getPreferredAction() {
|
||||
return preferredAction;
|
||||
}
|
||||
}
|
||||
|
140
Core/src/org/sleuthkit/autopsy/communications/relationships/MessageViewer.form
Executable file
140
Core/src/org/sleuthkit/autopsy/communications/relationships/MessageViewer.form
Executable file
@ -0,0 +1,140 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,3,-126,0,0,2,-76"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignCardLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="rootMessagesPane">
|
||||
<Properties>
|
||||
<Property name="opaque" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignCardLayout" value="org.netbeans.modules.form.compat2.layouts.DesignCardLayout$CardConstraintsDescription">
|
||||
<CardConstraints cardName="threads"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="threadsLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/relationships/Bundle.properties" key="MessageViewer.threadsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="15" insetsLeft="15" insetsBottom="9" insetsRight="0" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="showAllButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/relationships/Bundle.properties" key="MessageViewer.showAllButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="showAllButtonActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="15" insetsBottom="15" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel" name="rootTablePane">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.LineBorderInfo">
|
||||
<LineBorder/>
|
||||
</Border>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="1" gridWidth="2" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="15" insetsBottom="9" insetsRight="15" anchor="18" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="messagePanel">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignCardLayout" value="org.netbeans.modules.form.compat2.layouts.DesignCardLayout$CardConstraintsDescription">
|
||||
<CardConstraints cardName="messages"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="org.sleuthkit.autopsy.communications.relationships.MessagesPanel" name="threadMessagesPanel">
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new MessagesPanel()"/>
|
||||
</AuxValues>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="3" gridWidth="3" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="15" insetsBottom="0" insetsRight="15" anchor="18" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="backButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/relationships/Bundle.properties" key="MessageViewer.backButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AccessibilityProperties>
|
||||
<Property name="AccessibleContext.accessibleDescription" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/relationships/Bundle.properties" key="MessageViewer.backButton.AccessibleContext.accessibleDescription" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</AccessibilityProperties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="backButtonActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="2" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="9" insetsLeft="0" insetsBottom="9" insetsRight="15" anchor="13" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="showingMessagesLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/relationships/Bundle.properties" key="MessageViewer.showingMessagesLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="9" insetsLeft="15" insetsBottom="5" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="threadNameLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/relationships/Bundle.properties" key="MessageViewer.threadNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="9" insetsLeft="5" insetsBottom="5" insetsRight="15" anchor="17" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Form>
|
444
Core/src/org/sleuthkit/autopsy/communications/relationships/MessageViewer.java
Executable file
444
Core/src/org/sleuthkit/autopsy/communications/relationships/MessageViewer.java
Executable file
@ -0,0 +1,444 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> 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.communications.relationships;
|
||||
|
||||
import java.awt.CardLayout;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.KeyboardFocusManager;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyVetoException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import static javax.swing.SwingUtilities.isDescendingFrom;
|
||||
import org.netbeans.swing.outline.DefaultOutlineModel;
|
||||
import org.netbeans.swing.outline.Outline;
|
||||
import org.openide.explorer.ExplorerManager;
|
||||
import static org.openide.explorer.ExplorerUtils.createLookup;
|
||||
import org.openide.nodes.AbstractNode;
|
||||
import org.openide.nodes.Children;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.nodes.Node.Property;
|
||||
import org.openide.nodes.Node.PropertySet;
|
||||
import org.openide.util.Exceptions;
|
||||
import org.openide.util.Lookup;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.autopsy.communications.ModifiableProxyLookup;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
/**
|
||||
* The main panel for the messages tab of the RelationshipViewer
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
public class MessageViewer extends JPanel implements RelationshipsViewer {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(MessageViewer.class.getName());
|
||||
|
||||
private final ModifiableProxyLookup proxyLookup;
|
||||
private final PropertyChangeListener focusPropertyListener;
|
||||
private final ThreadChildNodeFactory rootMessageFactory;
|
||||
private final MessagesChildNodeFactory threadMessageNodeFactory;
|
||||
|
||||
private SelectionInfo currentSelectionInfo = null;
|
||||
|
||||
OutlineViewPanel currentPanel;
|
||||
|
||||
@Messages({
|
||||
"MessageViewer_tabTitle=Messages",
|
||||
"MessageViewer_columnHeader_From=From",
|
||||
"MessageViewer_columnHeader_Date=Date",
|
||||
"MessageViewer_columnHeader_To=To",
|
||||
"MessageViewer_columnHeader_EarlyDate=Earliest Message",
|
||||
"MessageViewer_columnHeader_Subject=Subject",
|
||||
"MessageViewer_columnHeader_Attms=Attachments",
|
||||
"MessageViewer_no_messages=<No messages found for selected account>",
|
||||
"MessageViewer_viewMessage_all=All",
|
||||
"MessageViewer_viewMessage_selected=Selected",
|
||||
"MessageViewer_viewMessage_unthreaded=Unthreaded",
|
||||
"MessageViewer_viewMessage_calllogs=Call Logs"})
|
||||
|
||||
/**
|
||||
* Creates new form MessageViewer
|
||||
*/
|
||||
public MessageViewer() {
|
||||
|
||||
initComponents();
|
||||
currentPanel = rootTablePane;
|
||||
proxyLookup = new ModifiableProxyLookup(createLookup(rootTablePane.getExplorerManager(), getActionMap()));
|
||||
rootMessageFactory = new ThreadChildNodeFactory(new ShowThreadMessagesAction());
|
||||
threadMessageNodeFactory = new MessagesChildNodeFactory();
|
||||
|
||||
// See org.sleuthkit.autopsy.timeline.TimeLineTopComponent for a detailed
|
||||
// explaination of focusPropertyListener
|
||||
focusPropertyListener = (final PropertyChangeEvent focusEvent) -> {
|
||||
if (focusEvent.getPropertyName().equalsIgnoreCase("focusOwner")) {
|
||||
final Component newFocusOwner = (Component) focusEvent.getNewValue();
|
||||
|
||||
if (newFocusOwner == null) {
|
||||
return;
|
||||
}
|
||||
if (isDescendingFrom(newFocusOwner, rootTablePane)) {
|
||||
proxyLookup.setNewLookups(createLookup(rootTablePane.getExplorerManager(), getActionMap()));
|
||||
} else if (isDescendingFrom(newFocusOwner, MessageViewer.this)) {
|
||||
proxyLookup.setNewLookups(createLookup(currentPanel.getExplorerManager(), getActionMap()));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
rootTablePane.getExplorerManager().setRootContext(
|
||||
new AbstractNode(Children.create(rootMessageFactory, true)));
|
||||
|
||||
rootTablePane.getOutlineView().setPopupAllowed(false);
|
||||
|
||||
Outline outline = rootTablePane.getOutlineView().getOutline();
|
||||
rootTablePane.getOutlineView().setPropertyColumns(
|
||||
"Date", Bundle.MessageViewer_columnHeader_EarlyDate(),
|
||||
"Subject", Bundle.MessageViewer_columnHeader_Subject()
|
||||
);
|
||||
outline.setRootVisible(false);
|
||||
((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel("Type");
|
||||
outline.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
|
||||
|
||||
rootTablePane.getExplorerManager().addPropertyChangeListener((PropertyChangeEvent evt) -> {
|
||||
if (evt.getPropertyName().equals(ExplorerManager.PROP_SELECTED_NODES)) {
|
||||
showSelectedThread();
|
||||
}
|
||||
});
|
||||
|
||||
threadMessagesPanel.setChildFactory(threadMessageNodeFactory);
|
||||
|
||||
rootTablePane.setTableColumnsWidth(10, 20, 70);
|
||||
|
||||
Image image = getScaledImage((new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/timeline/images/arrow-180.png"))).getImage(), 16, 16);
|
||||
backButton.setIcon(new ImageIcon(image) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return Bundle.MessageViewer_tabTitle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JPanel getPanel() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelectionInfo(SelectionInfo info) {
|
||||
currentSelectionInfo = info;
|
||||
|
||||
currentPanel = rootTablePane;
|
||||
|
||||
CardLayout layout = (CardLayout) this.getLayout();
|
||||
layout.show(this, "threads");
|
||||
|
||||
rootMessageFactory.refresh(info);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Lookup getLookup() {
|
||||
return proxyLookup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addNotify() {
|
||||
super.addNotify();
|
||||
//add listener that maintains correct selection in the Global Actions Context
|
||||
KeyboardFocusManager.getCurrentKeyboardFocusManager()
|
||||
.addPropertyChangeListener("focusOwner", focusPropertyListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeNotify() {
|
||||
super.removeNotify();
|
||||
KeyboardFocusManager.getCurrentKeyboardFocusManager()
|
||||
.removePropertyChangeListener("focusOwner", focusPropertyListener);
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private void showSelectedThread() {
|
||||
final Node[] nodes = rootTablePane.getExplorerManager().getSelectedNodes();
|
||||
|
||||
if (nodes == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (nodes.length == 0 || nodes.length > 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
ArrayList<String> threadIDList = new ArrayList<>();
|
||||
String subject = "";
|
||||
|
||||
PropertySet[] propertySets = nodes[0].getPropertySets();
|
||||
for (PropertySet pset : propertySets) {
|
||||
Property[] properties = pset.getProperties();
|
||||
for (Property prop : properties) {
|
||||
if (prop.getName().equalsIgnoreCase("threadid")) {
|
||||
try {
|
||||
String threadID = prop.getValue().toString();
|
||||
if (!threadIDList.contains(threadID)) {
|
||||
threadIDList.add(threadID);
|
||||
}
|
||||
} catch (IllegalAccessException | InvocationTargetException ex) {
|
||||
logger.log(Level.WARNING, String.format("Unable to get threadid for node: %s", nodes[0].getDisplayName()), ex);
|
||||
}
|
||||
} else if (prop.getName().equalsIgnoreCase("subject")) {
|
||||
try {
|
||||
subject = prop.getValue().toString();
|
||||
} catch (IllegalAccessException | InvocationTargetException ex) {
|
||||
logger.log(Level.WARNING, String.format("Unable to get subject for node: %s", nodes[0].getDisplayName()), ex);
|
||||
subject = "<unavailable>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!threadIDList.isEmpty()) {
|
||||
threadMessageNodeFactory.refresh(currentSelectionInfo, threadIDList);
|
||||
|
||||
if (!subject.isEmpty()) {
|
||||
threadNameLabel.setText(subject);
|
||||
} else {
|
||||
if (threadIDList.contains(MessageNode.CALL_LOG_ID)) {
|
||||
threadNameLabel.setText(Bundle.MessageViewer_viewMessage_calllogs());
|
||||
} else {
|
||||
threadNameLabel.setText(Bundle.MessageViewer_viewMessage_unthreaded());
|
||||
}
|
||||
}
|
||||
|
||||
showMessagesPane();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the threads pane visible.
|
||||
*/
|
||||
private void showThreadsPane() {
|
||||
switchCard("threads");
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the message pane visible.
|
||||
*/
|
||||
private void showMessagesPane() {
|
||||
switchCard("messages");
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the visible panel (card).
|
||||
*
|
||||
* @param cardName Name of card to show
|
||||
*/
|
||||
private void switchCard(String cardName) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
CardLayout layout = (CardLayout)getLayout();
|
||||
layout.show(MessageViewer.this, cardName);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Scales the given image to the given width and height.
|
||||
*
|
||||
* @param srcImg Image to scale
|
||||
* @param w Image width
|
||||
* @param h Image height
|
||||
*
|
||||
* @return Scaled version of srcImg
|
||||
*/
|
||||
private Image getScaledImage(Image srcImg, int w, int h){
|
||||
BufferedImage resizedImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics2D g2 = resizedImg.createGraphics();
|
||||
|
||||
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
|
||||
g2.drawImage(srcImg, 0, 0, w, h, null);
|
||||
g2.dispose();
|
||||
|
||||
return resizedImg;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
java.awt.GridBagConstraints gridBagConstraints;
|
||||
|
||||
rootMessagesPane = new javax.swing.JPanel();
|
||||
threadsLabel = new javax.swing.JLabel();
|
||||
showAllButton = new javax.swing.JButton();
|
||||
rootTablePane = new org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel();
|
||||
messagePanel = new javax.swing.JPanel();
|
||||
threadMessagesPanel = new MessagesPanel();
|
||||
backButton = new javax.swing.JButton();
|
||||
showingMessagesLabel = new javax.swing.JLabel();
|
||||
threadNameLabel = new javax.swing.JLabel();
|
||||
|
||||
setLayout(new java.awt.CardLayout());
|
||||
|
||||
rootMessagesPane.setOpaque(false);
|
||||
rootMessagesPane.setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(threadsLabel, org.openide.util.NbBundle.getMessage(MessageViewer.class, "MessageViewer.threadsLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(15, 15, 9, 0);
|
||||
rootMessagesPane.add(threadsLabel, gridBagConstraints);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(showAllButton, org.openide.util.NbBundle.getMessage(MessageViewer.class, "MessageViewer.showAllButton.text")); // NOI18N
|
||||
showAllButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
showAllButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 2;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 15, 15, 0);
|
||||
rootMessagesPane.add(showAllButton, gridBagConstraints);
|
||||
|
||||
rootTablePane.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.gridwidth = 2;
|
||||
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(0, 15, 9, 15);
|
||||
rootMessagesPane.add(rootTablePane, gridBagConstraints);
|
||||
|
||||
add(rootMessagesPane, "threads");
|
||||
|
||||
messagePanel.setLayout(new java.awt.GridBagLayout());
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 3;
|
||||
gridBagConstraints.gridwidth = 3;
|
||||
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(0, 15, 0, 15);
|
||||
messagePanel.add(threadMessagesPanel, gridBagConstraints);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(backButton, org.openide.util.NbBundle.getMessage(MessageViewer.class, "MessageViewer.backButton.text")); // NOI18N
|
||||
backButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
backButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 2;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(9, 0, 9, 15);
|
||||
messagePanel.add(backButton, gridBagConstraints);
|
||||
backButton.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(MessageViewer.class, "MessageViewer.backButton.AccessibleContext.accessibleDescription")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(showingMessagesLabel, org.openide.util.NbBundle.getMessage(MessageViewer.class, "MessageViewer.showingMessagesLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(9, 15, 5, 0);
|
||||
messagePanel.add(showingMessagesLabel, gridBagConstraints);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(threadNameLabel, org.openide.util.NbBundle.getMessage(MessageViewer.class, "MessageViewer.threadNameLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(9, 5, 5, 15);
|
||||
messagePanel.add(threadNameLabel, gridBagConstraints);
|
||||
|
||||
add(messagePanel, "messages");
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void backButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_backButtonActionPerformed
|
||||
try {
|
||||
rootTablePane.getExplorerManager().setSelectedNodes(new Node[0]);
|
||||
} catch (PropertyVetoException ex) {
|
||||
Exceptions.printStackTrace(ex);
|
||||
}
|
||||
showThreadsPane();
|
||||
}//GEN-LAST:event_backButtonActionPerformed
|
||||
|
||||
private void showAllButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showAllButtonActionPerformed
|
||||
threadMessageNodeFactory.refresh(currentSelectionInfo, null);
|
||||
threadNameLabel.setText("All Messages");
|
||||
|
||||
showMessagesPane();
|
||||
}//GEN-LAST:event_showAllButtonActionPerformed
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JButton backButton;
|
||||
private javax.swing.JPanel messagePanel;
|
||||
private javax.swing.JPanel rootMessagesPane;
|
||||
private org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel rootTablePane;
|
||||
private javax.swing.JButton showAllButton;
|
||||
private javax.swing.JLabel showingMessagesLabel;
|
||||
private org.sleuthkit.autopsy.communications.relationships.MessagesPanel threadMessagesPanel;
|
||||
private javax.swing.JLabel threadNameLabel;
|
||||
private javax.swing.JLabel threadsLabel;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
/**
|
||||
* The preferred action of the table nodes.
|
||||
*/
|
||||
class ShowThreadMessagesAction extends AbstractAction {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
showSelectedThread();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -18,98 +18,194 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.communications.relationships;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import org.openide.nodes.ChildFactory;
|
||||
import org.openide.nodes.Node;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.CommunicationsManager;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* ChildFactory that creates createKeys and nodes from a given selectionInfo for
|
||||
* only emails, call logs and messages.
|
||||
* A ChildFactory subclass for creating MessageNodes from a set of
|
||||
* BlackboardArtifact objects.
|
||||
*
|
||||
*/
|
||||
final class MessagesChildNodeFactory extends ChildFactory<BlackboardArtifact> {
|
||||
public class MessagesChildNodeFactory extends ChildFactory<BlackboardArtifact>{
|
||||
|
||||
private static final Logger logger = Logger.getLogger(MessagesChildNodeFactory.class.getName());
|
||||
|
||||
private SelectionInfo selectionInfo;
|
||||
|
||||
/**
|
||||
* Construct a new MessageChildNodeFactory from the currently selectionInfo
|
||||
*
|
||||
* @param selectionInfo SelectionInfo object for the currently selected
|
||||
* accounts
|
||||
*/
|
||||
MessagesChildNodeFactory(SelectionInfo selectionInfo) {
|
||||
|
||||
private List<String> threadIDs;
|
||||
|
||||
MessagesChildNodeFactory(SelectionInfo selectionInfo, List<String> threadIDs) {
|
||||
this.selectionInfo = selectionInfo;
|
||||
this.threadIDs = threadIDs;
|
||||
}
|
||||
|
||||
MessagesChildNodeFactory() {
|
||||
this(null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the current instance of selectionInfo and calls the refresh method.
|
||||
*
|
||||
* @param selectionInfo New instance of the currently selected accounts
|
||||
* @param threadIDs A list of threadIDs to filter the keys by, null will
|
||||
* return all keys for the selected accounts.
|
||||
*/
|
||||
public void refresh(SelectionInfo selectionInfo) {
|
||||
this.selectionInfo = selectionInfo;
|
||||
public void refresh(SelectionInfo selectionInfo, List<String> threadIDs) {
|
||||
this.threadIDs = threadIDs;
|
||||
this.selectionInfo = selectionInfo;
|
||||
refresh(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a list of Keys (BlackboardArtifact) for only messages for the
|
||||
* currently selected accounts
|
||||
*
|
||||
* @param list List of BlackboardArtifact to populate
|
||||
*
|
||||
* @return True on success
|
||||
*/
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<BlackboardArtifact> list) {
|
||||
CommunicationsManager communicationManager;
|
||||
try {
|
||||
communicationManager = Case.getCurrentCaseThrows().getSleuthkitCase().getCommunicationsManager();
|
||||
} catch (NoCurrentCaseException | TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to get communications manager from case.", ex); //NON-NLS
|
||||
return false;
|
||||
}
|
||||
|
||||
if(selectionInfo == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
final Set<Content> relationshipSources;
|
||||
try {
|
||||
relationshipSources = selectionInfo.getRelationshipSources();
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to load relationship sources.", ex); //NON-NLS
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
relationshipSources = communicationManager.getRelationshipSources(selectionInfo.getAccountDevicesInstances(), selectionInfo.getCommunicationsFilter());
|
||||
|
||||
relationshipSources.stream().filter((content) -> (content instanceof BlackboardArtifact)).forEachOrdered((content) -> {
|
||||
|
||||
for(Content content: relationshipSources) {
|
||||
if( !(content instanceof BlackboardArtifact)){
|
||||
continue;
|
||||
}
|
||||
|
||||
BlackboardArtifact bba = (BlackboardArtifact) content;
|
||||
BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(bba.getArtifactTypeID());
|
||||
|
||||
if (fromID == BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG
|
||||
|| fromID == BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG
|
||||
|| fromID == BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE) {
|
||||
if (fromID != BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG
|
||||
&& fromID != BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG
|
||||
&& fromID != BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// We want email and message artifacts that do not have "threadIDs" to appear as one thread in the UI
|
||||
// To achive this assign any artifact that does not have a threadID
|
||||
// the "UNTHREADED_ID"
|
||||
// All call logs will default to a single call logs thread
|
||||
String artifactThreadID;
|
||||
if (fromID == BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG) {
|
||||
artifactThreadID = MessageNode.CALL_LOG_ID;
|
||||
} else {
|
||||
artifactThreadID = MessageNode.UNTHREADED_ID;
|
||||
}
|
||||
BlackboardAttribute attribute = bba.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_THREAD_ID));
|
||||
|
||||
if(attribute != null) {
|
||||
artifactThreadID = attribute.getValueString();
|
||||
}
|
||||
|
||||
if(threadIDs == null || threadIDs.contains(artifactThreadID)) {
|
||||
list.add(bba);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to get relationship sources.", ex); //NON-NLS
|
||||
logger.log(Level.SEVERE, "Failed to load artifacts for relationship sources.", ex); //NON-NLS
|
||||
}
|
||||
|
||||
list.sort(new DateComparator());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Node createNodeForKey(BlackboardArtifact key) {
|
||||
return new MessageNode(key);
|
||||
return new MessageNode(key, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* A comparator class for comparing BlackboardArtifacts of type
|
||||
* TSK_EMAIL_MSG, TSK_MESSAGE, and TSK_CALLLOG by their respective creation
|
||||
* date-time.
|
||||
*/
|
||||
class DateComparator implements Comparator<BlackboardArtifact> {
|
||||
@Override
|
||||
public int compare(BlackboardArtifact bba1, BlackboardArtifact bba2) {
|
||||
|
||||
BlackboardAttribute attribute1 = null;
|
||||
BlackboardAttribute attribute2 = null;
|
||||
// Inializing to Long.MAX_VALUE so that if a BlackboardArtifact of
|
||||
// any unexpected type is passed in, it will bubble to the top of
|
||||
// the list.
|
||||
long dateTime1 = Long.MAX_VALUE;
|
||||
long dateTime2 = Long.MAX_VALUE;
|
||||
|
||||
if (bba1 != null) {
|
||||
BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(bba1.getArtifactTypeID());
|
||||
if (fromID != null) {
|
||||
try {
|
||||
switch (fromID) {
|
||||
case TSK_EMAIL_MSG:
|
||||
attribute1 = bba1.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT));
|
||||
break;
|
||||
case TSK_MESSAGE:
|
||||
attribute1 = bba1.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME));
|
||||
break;
|
||||
case TSK_CALLLOG:
|
||||
attribute1 = bba1.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START));
|
||||
break;
|
||||
default:
|
||||
attribute1 = null;
|
||||
break;
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, String.format("Unable to compare attributes for artifact %d", bba1.getArtifactID()), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bba2 != null) {
|
||||
BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(bba2.getArtifactTypeID());
|
||||
if (fromID != null) {
|
||||
try {
|
||||
switch (fromID) {
|
||||
case TSK_EMAIL_MSG:
|
||||
attribute2 = bba2.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT));
|
||||
break;
|
||||
case TSK_MESSAGE:
|
||||
attribute2 = bba2.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME));
|
||||
break;
|
||||
case TSK_CALLLOG:
|
||||
attribute2 = bba2.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START));
|
||||
break;
|
||||
default:
|
||||
attribute2 = null;
|
||||
break;
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, String.format("Unable to compare attributes for artifact %d", bba2.getArtifactID()), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (attribute1 != null) {
|
||||
dateTime1 = attribute1.getValueLong();
|
||||
}
|
||||
|
||||
if (attribute2 != null) {
|
||||
dateTime2 = attribute2.getValueLong();
|
||||
}
|
||||
|
||||
return Long.compare(dateTime1, dateTime2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JSplitPane" name="splitPane">
|
||||
<Properties>
|
||||
<Property name="orientation" type="int" value="0"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
|
||||
<BorderConstraints direction="Center"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel" name="outlineViewPanel">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||
<JSplitPaneConstraints position="left"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="org.sleuthkit.autopsy.contentviewers.MessageContentViewer" name="messageContentViewer">
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new MessageDataContent()"/>
|
||||
</AuxValues>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||
<JSplitPaneConstraints position="right"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Form>
|
@ -6,7 +6,7 @@
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obt ain a copy of the License at
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
@ -22,56 +22,38 @@ import java.awt.Component;
|
||||
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;
|
||||
import org.openide.explorer.ExplorerManager;
|
||||
import static org.openide.explorer.ExplorerUtils.createLookup;
|
||||
import org.openide.nodes.AbstractNode;
|
||||
import org.openide.nodes.ChildFactory;
|
||||
import org.openide.nodes.Children;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.nodes.NodeAdapter;
|
||||
import org.openide.nodes.NodeMemberEvent;
|
||||
import org.openide.util.Lookup;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.sleuthkit.autopsy.communications.ModifiableProxyLookup;
|
||||
import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
|
||||
import org.sleuthkit.autopsy.directorytree.DataResultFilterNode;
|
||||
|
||||
/**
|
||||
* Visualation for the messages of the currently selected accounts.
|
||||
*
|
||||
* General Purpose class for panels that need OutlineView of message nodes at
|
||||
* the top with a MessageContentViewer at the bottom.
|
||||
*/
|
||||
@ServiceProvider(service = RelationshipsViewer.class)
|
||||
public final class MessagesViewer extends JPanel implements RelationshipsViewer {
|
||||
public class MessagesPanel extends javax.swing.JPanel implements Lookup.Provider {
|
||||
|
||||
private final Outline outline;
|
||||
private final ModifiableProxyLookup proxyLookup;
|
||||
private final PropertyChangeListener focusPropertyListener;
|
||||
private final MessagesChildNodeFactory nodeFactory;
|
||||
|
||||
@Messages({
|
||||
"MessageViewer_tabTitle=Messages",
|
||||
"MessageViewer_columnHeader_From=From",
|
||||
"MessageViewer_columnHeader_To=To",
|
||||
"MessageViewer_columnHeader_Date=Date",
|
||||
"MessageViewer_columnHeader_Subject=Subject",
|
||||
"MessageViewer_columnHeader_Attms=Attachments",
|
||||
"MessageViewer_no_messages=<No messages found for selected account>"
|
||||
})
|
||||
|
||||
|
||||
/**
|
||||
* Visualation for the messages of the currently selected accounts.
|
||||
* Creates new form MessagesPanel
|
||||
*/
|
||||
public MessagesViewer() {
|
||||
public MessagesPanel() {
|
||||
initComponents();
|
||||
|
||||
outlineViewPanel.hideOutlineView(Bundle.MessageViewer_no_messages());
|
||||
|
||||
proxyLookup = new ModifiableProxyLookup(createLookup(outlineViewPanel.getExplorerManager(), getActionMap()));
|
||||
nodeFactory = new MessagesChildNodeFactory(null);
|
||||
|
||||
// See org.sleuthkit.autopsy.timeline.TimeLineTopComponent for a detailed
|
||||
// explaination of focusPropertyListener
|
||||
@ -82,10 +64,10 @@ public final class MessagesViewer extends JPanel implements RelationshipsViewer
|
||||
if (newFocusOwner == null) {
|
||||
return;
|
||||
}
|
||||
if (isDescendingFrom(newFocusOwner, contentViewer)) {
|
||||
if (isDescendingFrom(newFocusOwner, messageContentViewer)) {
|
||||
//if the focus owner is within the MessageContentViewer (the attachments table)
|
||||
proxyLookup.setNewLookups(createLookup(((MessageDataContent) contentViewer).getExplorerManager(), getActionMap()));
|
||||
} else if (isDescendingFrom(newFocusOwner, MessagesViewer.this)) {
|
||||
proxyLookup.setNewLookups(createLookup(((MessageDataContent) messageContentViewer).getExplorerManager(), getActionMap()));
|
||||
} else if (isDescendingFrom(newFocusOwner, MessagesPanel.this)) {
|
||||
//... or if it is within the Results table.
|
||||
proxyLookup.setNewLookups(createLookup(outlineViewPanel.getExplorerManager(), getActionMap()));
|
||||
|
||||
@ -109,52 +91,24 @@ public final class MessagesViewer extends JPanel implements RelationshipsViewer
|
||||
final Node[] nodes = outlineViewPanel.getExplorerManager().getSelectedNodes();
|
||||
|
||||
if (nodes != null && nodes.length == 1) {
|
||||
contentViewer.setNode(nodes[0]);
|
||||
messageContentViewer.setNode(nodes[0]);
|
||||
}
|
||||
else {
|
||||
contentViewer.setNode(null);
|
||||
messageContentViewer.setNode(null);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
outlineViewPanel.getExplorerManager().setRootContext(
|
||||
new TableFilterNode(
|
||||
new DataResultFilterNode(
|
||||
new AbstractNode(
|
||||
Children.create(nodeFactory, true)),
|
||||
outlineViewPanel.getExplorerManager()),
|
||||
true));
|
||||
|
||||
// When a new set of nodes are added to the OutlineView the childrenAdded
|
||||
// seems to be fired before the childrenRemoved.
|
||||
outlineViewPanel.getExplorerManager().getRootContext().addNodeListener(new NodeAdapter() {
|
||||
@Override
|
||||
public void childrenAdded(NodeMemberEvent nme) {
|
||||
updateOutlineViewPanel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void childrenRemoved(NodeMemberEvent nme) {
|
||||
updateOutlineViewPanel();
|
||||
}
|
||||
});
|
||||
splitPane.setResizeWeight(0.5);
|
||||
splitPane.setDividerLocation(0.5);
|
||||
outlineViewPanel.setTableColumnsWidth(5,10,10,15,50,10);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return Bundle.MessageViewer_tabTitle();
|
||||
|
||||
public MessagesPanel(ChildFactory<?> nodeFactory) {
|
||||
this();
|
||||
setChildFactory(nodeFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JPanel getPanel() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelectionInfo(SelectionInfo info) {
|
||||
nodeFactory.refresh(info);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Lookup getLookup() {
|
||||
return proxyLookup;
|
||||
@ -174,16 +128,16 @@ public final class MessagesViewer extends JPanel implements RelationshipsViewer
|
||||
KeyboardFocusManager.getCurrentKeyboardFocusManager()
|
||||
.removePropertyChangeListener("focusOwner", focusPropertyListener);
|
||||
}
|
||||
|
||||
private void updateOutlineViewPanel() {
|
||||
int nodeCount = outlineViewPanel.getExplorerManager().getRootContext().getChildren().getNodesCount();
|
||||
if(nodeCount == 0) {
|
||||
outlineViewPanel.hideOutlineView(Bundle.MessageViewer_no_messages());
|
||||
} else {
|
||||
outlineViewPanel.showOutlineView();
|
||||
}
|
||||
}
|
||||
|
||||
final void setChildFactory(ChildFactory<?> nodeFactory) {
|
||||
outlineViewPanel.getExplorerManager().setRootContext(
|
||||
new TableFilterNode(
|
||||
new DataResultFilterNode(
|
||||
new AbstractNode(
|
||||
Children.create(nodeFactory, true)),
|
||||
outlineViewPanel.getExplorerManager()),true));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -193,28 +147,23 @@ public final class MessagesViewer extends JPanel implements RelationshipsViewer
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
|
||||
contentViewer = new MessageDataContent();
|
||||
splitPane = new javax.swing.JSplitPane();
|
||||
outlineViewPanel = new org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel();
|
||||
messageContentViewer = new MessageDataContent();
|
||||
|
||||
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.BorderLayout());
|
||||
|
||||
splitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
|
||||
splitPane.setLeftComponent(outlineViewPanel);
|
||||
splitPane.setRightComponent(messageContentViewer);
|
||||
|
||||
add(splitPane, java.awt.BorderLayout.CENTER);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private org.sleuthkit.autopsy.contentviewers.MessageContentViewer contentViewer;
|
||||
private org.sleuthkit.autopsy.contentviewers.MessageContentViewer messageContentViewer;
|
||||
private org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel outlineViewPanel;
|
||||
private javax.swing.JSplitPane splitPane;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.4" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="contentViewer" max="32767" attributes="0"/>
|
||||
<Component id="outlineViewPanel" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="outlineViewPanel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="contentViewer" pref="390" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="org.sleuthkit.autopsy.contentviewers.MessageContentViewer" name="contentViewer">
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new MessageDataContent()"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel" name="outlineViewPanel">
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
@ -20,11 +20,6 @@
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="org.openide.explorer.view.OutlineView" name="outlineView">
|
||||
<Properties>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[300, 400]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignCardLayout" value="org.netbeans.modules.form.compat2.layouts.DesignCardLayout$CardConstraintsDescription">
|
||||
<CardConstraints cardName="outlineCard"/>
|
||||
|
@ -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,6 +100,28 @@ public class OutlineViewPanel extends javax.swing.JPanel implements ExplorerMana
|
||||
super.setEnabled(enabled);
|
||||
outlineView.setEnabled(enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the width of the columns of the OutlineView based on the passed in
|
||||
* list of percentages. There should be on double value for each column
|
||||
* in the OutlineView.
|
||||
*
|
||||
* @param percentages A series of double percentages values representing
|
||||
* what percent of the total width of the table each
|
||||
* column should have.
|
||||
*/
|
||||
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.
|
||||
@ -113,8 +137,6 @@ public class OutlineViewPanel extends javax.swing.JPanel implements ExplorerMana
|
||||
messageLabel = new javax.swing.JLabel();
|
||||
|
||||
setLayout(new java.awt.CardLayout(5, 5));
|
||||
|
||||
outlineView.setPreferredSize(new java.awt.Dimension(300, 400));
|
||||
add(outlineView, "outlineCard");
|
||||
|
||||
messagePanel.setLayout(new java.awt.BorderLayout());
|
||||
|
@ -13,40 +13,19 @@
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<EmptySpace min="0" pref="400" max="32767" attributes="0"/>
|
||||
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
||||
<Component id="scrollPane" alignment="1" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<EmptySpace min="0" pref="300" max="32767" attributes="0"/>
|
||||
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
||||
<Component id="scrollPane" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JScrollPane" name="scrollPane">
|
||||
<Properties>
|
||||
<Property name="verticalScrollBarPolicy" type="int" value="21"/>
|
||||
</Properties>
|
||||
<Container class="javax.swing.JTabbedPane" name="tabPane">
|
||||
<Events>
|
||||
<EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="tabPaneStateChanged"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JTabbedPane" name="tabPane">
|
||||
<Events>
|
||||
<EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="tabPaneStateChanged"/>
|
||||
</Events>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout"/>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout"/>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -31,7 +31,7 @@ public final class RelationshipBrowser extends JPanel implements Lookup.Provider
|
||||
|
||||
private SelectionInfo currentSelection;
|
||||
|
||||
private final MessagesViewer messagesViewer;
|
||||
private final MessageViewer messagesViewer;
|
||||
private final ContactsViewer contactsViewer;
|
||||
private final SummaryViewer summaryViewer;
|
||||
private final MediaViewer mediaViewer;
|
||||
@ -42,26 +42,23 @@ public final class RelationshipBrowser extends JPanel implements Lookup.Provider
|
||||
* Creates new form RelationshipBrowser
|
||||
*/
|
||||
public RelationshipBrowser() {
|
||||
messagesViewer = new MessagesViewer();
|
||||
initComponents();
|
||||
messagesViewer = new MessageViewer();
|
||||
contactsViewer = new ContactsViewer();
|
||||
summaryViewer = new SummaryViewer();
|
||||
mediaViewer = new MediaViewer();
|
||||
|
||||
proxyLookup = new ModifiableProxyLookup(messagesViewer.getLookup());
|
||||
|
||||
initComponents();
|
||||
|
||||
|
||||
tabPane.add(summaryViewer.getDisplayName(), summaryViewer);
|
||||
tabPane.add(messagesViewer.getDisplayName(), messagesViewer);
|
||||
tabPane.add(contactsViewer.getDisplayName(), contactsViewer);
|
||||
tabPane.add(mediaViewer.getDisplayName(), mediaViewer);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of currentSelection and passes the SelectionInfo onto the
|
||||
* currently selected\visible tab.
|
||||
* currently selected, visible tab.
|
||||
*
|
||||
* @param info Currently selected account nodes
|
||||
*/
|
||||
@ -78,33 +75,25 @@ public final class RelationshipBrowser extends JPanel implements Lookup.Provider
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//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;
|
||||
add(tabPane, gridBagConstraints);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void tabPaneStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_tabPaneStateChanged
|
||||
@ -121,7 +110,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
|
||||
|
||||
|
@ -40,7 +40,8 @@ public final class SelectionInfo {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(SelectionInfo.class.getName());
|
||||
|
||||
private final Set<AccountDeviceInstance> accountDeviceInstances;
|
||||
private final Set<AccountDeviceInstance> selectedNodes;
|
||||
private final Set<GraphEdge> selectedEdges;
|
||||
private final CommunicationsFilter communicationFilter;
|
||||
private final Set<Account> accounts;
|
||||
|
||||
@ -50,26 +51,38 @@ public final class SelectionInfo {
|
||||
/**
|
||||
* Wraps the details of the currently selected accounts.
|
||||
*
|
||||
* @param accountDeviceInstances Selected accountDecivedInstances
|
||||
* @param selectedNodes Selected AccountDeviceInstances
|
||||
* @param selectedEdges Selected pairs of AccountDeviceInstances
|
||||
* @param communicationFilter Currently selected communications filters
|
||||
*/
|
||||
public SelectionInfo(Set<AccountDeviceInstance> accountDeviceInstances, CommunicationsFilter communicationFilter) {
|
||||
this.accountDeviceInstances = accountDeviceInstances;
|
||||
public SelectionInfo(Set<AccountDeviceInstance> selectedNodes, Set<GraphEdge> selectedEdges,
|
||||
CommunicationsFilter communicationFilter) {
|
||||
this.selectedNodes = selectedNodes;
|
||||
this.selectedEdges = selectedEdges;
|
||||
this.communicationFilter = communicationFilter;
|
||||
|
||||
accounts = new HashSet<>();
|
||||
accountDeviceInstances.forEach((instance) -> {
|
||||
selectedNodes.forEach((instance) -> {
|
||||
accounts.add(instance.getAccount());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently selected accountDeviceInstances
|
||||
* Returns the currently selected nodes
|
||||
*
|
||||
* @return Set of AccountDeviceInstance
|
||||
*/
|
||||
public Set<AccountDeviceInstance> getAccountDevicesInstances() {
|
||||
return accountDeviceInstances;
|
||||
public Set<AccountDeviceInstance> getSelectedNodes() {
|
||||
return selectedNodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently selected edges
|
||||
*
|
||||
* @return Set of GraphEdge objects
|
||||
*/
|
||||
public Set<GraphEdge> getSelectedEdges() {
|
||||
return selectedEdges;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -85,28 +98,50 @@ public final class SelectionInfo {
|
||||
return accounts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the set of relationship sources from the case database
|
||||
*
|
||||
* @return the relationship sources (may be empty)
|
||||
* @throws TskCoreException
|
||||
*/
|
||||
Set<Content> getRelationshipSources() throws TskCoreException {
|
||||
|
||||
CommunicationsManager communicationManager;
|
||||
try {
|
||||
communicationManager = Case.getCurrentCaseThrows().getSleuthkitCase().getCommunicationsManager();
|
||||
} catch (NoCurrentCaseException ex) {
|
||||
throw new TskCoreException("Failed to get current case", ex);
|
||||
}
|
||||
|
||||
Set<Content> relationshipSources = new HashSet<>();
|
||||
try {
|
||||
// Add all nodes
|
||||
relationshipSources.addAll(communicationManager.getRelationshipSources(getSelectedNodes(), getCommunicationsFilter()));
|
||||
|
||||
// Add all edges. For edges, the relationship has to include both endpoints
|
||||
for (SelectionInfo.GraphEdge edge : getSelectedEdges()) {
|
||||
relationshipSources.addAll(communicationManager.getRelationshipSources(edge.getStartNode(),
|
||||
edge.getEndNode(), getCommunicationsFilter()));
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to get relationships from case database.", ex); //NON-NLS
|
||||
|
||||
}
|
||||
return relationshipSources;
|
||||
}
|
||||
|
||||
public Set<BlackboardArtifact> getArtifacts() {
|
||||
if(accountArtifacts == null) {
|
||||
accountArtifacts = new HashSet<>();
|
||||
CommunicationsManager communicationManager;
|
||||
|
||||
try {
|
||||
communicationManager = Case.getCurrentCaseThrows().getSleuthkitCase().getCommunicationsManager();
|
||||
} catch (NoCurrentCaseException | TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to get communications manager from case.", ex); //NON-NLS
|
||||
return null;
|
||||
}
|
||||
|
||||
final Set<Content> relationshipSources;
|
||||
|
||||
try {
|
||||
relationshipSources = communicationManager.getRelationshipSources(getAccountDevicesInstances(), getCommunicationsFilter());
|
||||
|
||||
final Set<Content> relationshipSources = getRelationshipSources();
|
||||
relationshipSources.stream().filter((content) -> (content instanceof BlackboardArtifact)).forEachOrdered((content) -> {
|
||||
accountArtifacts.add((BlackboardArtifact) content);
|
||||
});
|
||||
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to get relationship sources.", ex); //NON-NLS
|
||||
logger.log(Level.SEVERE, "Failed to load relationship sources.", ex); //NON-NLS
|
||||
return accountArtifacts;
|
||||
}
|
||||
}
|
||||
|
||||
@ -182,4 +217,24 @@ public final class SelectionInfo {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility class to represent an edge from the graph visualization.
|
||||
*/
|
||||
public static class GraphEdge {
|
||||
AccountDeviceInstance startNode;
|
||||
AccountDeviceInstance endNode;
|
||||
|
||||
public GraphEdge(AccountDeviceInstance startNode, AccountDeviceInstance endNode) {
|
||||
this.startNode = startNode;
|
||||
this.endNode = endNode;
|
||||
}
|
||||
|
||||
public AccountDeviceInstance getStartNode() {
|
||||
return startNode;
|
||||
}
|
||||
|
||||
public AccountDeviceInstance getEndNode() {
|
||||
return endNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,36 +11,10 @@
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,4,7,0,0,4,-35"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="countsPanel" max="32767" attributes="0"/>
|
||||
<Component id="fileReferencesPanel" alignment="0" pref="485" max="32767" attributes="0"/>
|
||||
<Component id="caseReferencesPanel" alignment="1" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="countsPanel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="fileReferencesPanel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="caseReferencesPanel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="countsPanel">
|
||||
<Properties>
|
||||
@ -52,6 +26,11 @@
|
||||
</Border>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
@ -59,21 +38,19 @@
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="attachmentsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="messagesLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="callLogsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="contactsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="emailLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="attachmentsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="emailDataLabel" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="attachmentsDataLabel" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="contactsDataLabel" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="callLogsDataLabel" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="messagesDataLabel" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="attachmentsDataLabel" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<EmptySpace pref="959" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -81,11 +58,6 @@
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="7" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="attachmentsLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="attachmentsDataLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="messagesLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="messagesDataLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
@ -102,8 +74,8 @@
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="emailLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="emailDataLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="attachmentsLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="attachmentsDataLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
@ -111,13 +83,6 @@
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="emailLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/relationships/Bundle.properties" key="SummaryViewer.emailLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="contactsLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
@ -174,16 +139,9 @@
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="emailDataLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/relationships/Bundle.properties" key="SummaryViewer.emailDataLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="org.sleuthkit.autopsy.communications.OutlineViewPanel" name="fileReferencesPanel">
|
||||
<Component class="org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel" name="fileReferencesPanel">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||
@ -192,12 +150,14 @@
|
||||
</TitledBorder>
|
||||
</Border>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[472, 300]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="org.sleuthkit.autopsy.communications.OutlineViewPanel" name="caseReferencesPanel">
|
||||
<Component class="org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel" name="caseReferencesPanel">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||
@ -206,10 +166,12 @@
|
||||
</TitledBorder>
|
||||
</Border>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[472, 300]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="2" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -46,8 +46,8 @@ public class SummaryViewer extends javax.swing.JPanel implements RelationshipsVi
|
||||
"SummaryViewer_FileRefNameColumn_Title=Path",
|
||||
"SummaryViewer_CaseRefNameColumn_Title=Case Name",
|
||||
"SummaryViewer_CentralRepository_Message=<Enable Central Resposity to see Other Occurrences>",
|
||||
"SummaryViewer_Creation_Date_Title=Creation Date"
|
||||
})
|
||||
"SummaryViewer_Creation_Date_Title=Creation Date",
|
||||
"SummeryViewer_FileRef_Message=<Select one Accout to see File References>",})
|
||||
|
||||
/**
|
||||
* Creates new form SummaryViewer
|
||||
@ -70,6 +70,9 @@ public class SummaryViewer extends javax.swing.JPanel implements RelationshipsVi
|
||||
((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(Bundle.SummaryViewer_CaseRefNameColumn_Title());
|
||||
|
||||
clearControls();
|
||||
|
||||
caseReferencesPanel.hideOutlineView(Bundle.SummaryViewer_CentralRepository_Message());
|
||||
fileReferencesPanel.hideOutlineView(Bundle.SummeryViewer_FileRef_Message());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -97,14 +100,16 @@ public class SummaryViewer extends javax.swing.JPanel implements RelationshipsVi
|
||||
setEnabled(false);
|
||||
clearControls();
|
||||
|
||||
fileReferencesPanel.hideOutlineView(Bundle.SummeryViewer_FileRef_Message());
|
||||
} else {
|
||||
SelectionSummary summaryDetails = info.getSummary();
|
||||
|
||||
attachmentsDataLabel.setText(Integer.toString(summaryDetails.getAttachmentCnt()));
|
||||
callLogsDataLabel.setText(Integer.toString(summaryDetails.getCallLogCnt()));
|
||||
contactsDataLabel.setText(Integer.toString(summaryDetails.getContactsCnt()));
|
||||
emailDataLabel.setText(Integer.toString(summaryDetails.getEmailCnt()));
|
||||
messagesDataLabel.setText(Integer.toString(summaryDetails.getMessagesCnt()));
|
||||
messagesDataLabel.setText(Integer.toString(summaryDetails.getMessagesCnt() + summaryDetails.getEmailCnt()));
|
||||
|
||||
fileReferencesPanel.showOutlineView();
|
||||
|
||||
fileReferencesPanel.setNode(new AbstractNode(Children.create(new AccountSourceContentChildNodeFactory(info.getAccounts()), true)));
|
||||
caseReferencesPanel.setNode(new AbstractNode(Children.create(new CorrelationCaseChildNodeFactory(info.getAccounts()), true)));
|
||||
@ -129,7 +134,6 @@ public class SummaryViewer extends javax.swing.JPanel implements RelationshipsVi
|
||||
attachmentsLabel.setEnabled(enabled);
|
||||
callLogsLabel.setEnabled(enabled);
|
||||
contactsLabel.setEnabled(enabled);
|
||||
emailLabel.setEnabled(enabled);
|
||||
messagesLabel.setEnabled(enabled);
|
||||
caseReferencesPanel.setEnabled(enabled);
|
||||
fileReferencesPanel.setEnabled(enabled);
|
||||
@ -143,7 +147,6 @@ public class SummaryViewer extends javax.swing.JPanel implements RelationshipsVi
|
||||
attachmentsDataLabel.setText("");
|
||||
callLogsDataLabel.setText("");
|
||||
contactsDataLabel.setText("");
|
||||
emailDataLabel.setText("");
|
||||
messagesDataLabel.setText("");
|
||||
|
||||
fileReferencesPanel.setNode(new AbstractNode(Children.LEAF));
|
||||
@ -178,9 +181,9 @@ public class SummaryViewer extends javax.swing.JPanel implements RelationshipsVi
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
java.awt.GridBagConstraints gridBagConstraints;
|
||||
|
||||
countsPanel = new javax.swing.JPanel();
|
||||
emailLabel = new javax.swing.JLabel();
|
||||
contactsLabel = new javax.swing.JLabel();
|
||||
messagesLabel = new javax.swing.JLabel();
|
||||
callLogsLabel = new javax.swing.JLabel();
|
||||
@ -189,13 +192,12 @@ public class SummaryViewer extends javax.swing.JPanel implements RelationshipsVi
|
||||
messagesDataLabel = new javax.swing.JLabel();
|
||||
callLogsDataLabel = new javax.swing.JLabel();
|
||||
contactsDataLabel = new javax.swing.JLabel();
|
||||
emailDataLabel = new javax.swing.JLabel();
|
||||
fileReferencesPanel = new org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel();
|
||||
caseReferencesPanel = new org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel();
|
||||
|
||||
countsPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(SummaryViewer.class, "SummaryViewer.countsPanel.border.title"))); // NOI18N
|
||||
setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(emailLabel, org.openide.util.NbBundle.getMessage(SummaryViewer.class, "SummaryViewer.emailLabel.text")); // NOI18N
|
||||
countsPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(SummaryViewer.class, "SummaryViewer.countsPanel.border.title"))); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(contactsLabel, org.openide.util.NbBundle.getMessage(SummaryViewer.class, "SummaryViewer.contactsLabel.text")); // NOI18N
|
||||
|
||||
@ -213,8 +215,6 @@ public class SummaryViewer extends javax.swing.JPanel implements RelationshipsVi
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(contactsDataLabel, org.openide.util.NbBundle.getMessage(SummaryViewer.class, "SummaryViewer.contactsDataLabel.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(emailDataLabel, org.openide.util.NbBundle.getMessage(SummaryViewer.class, "SummaryViewer.emailDataLabel.text")); // NOI18N
|
||||
|
||||
javax.swing.GroupLayout countsPanelLayout = new javax.swing.GroupLayout(countsPanel);
|
||||
countsPanel.setLayout(countsPanelLayout);
|
||||
countsPanelLayout.setHorizontalGroup(
|
||||
@ -222,28 +222,22 @@ public class SummaryViewer extends javax.swing.JPanel implements RelationshipsVi
|
||||
.addGroup(countsPanelLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(countsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(attachmentsLabel)
|
||||
.addComponent(messagesLabel)
|
||||
.addComponent(callLogsLabel)
|
||||
.addComponent(contactsLabel)
|
||||
.addComponent(emailLabel))
|
||||
.addComponent(attachmentsLabel))
|
||||
.addGap(18, 18, 18)
|
||||
.addGroup(countsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(emailDataLabel)
|
||||
.addComponent(attachmentsDataLabel)
|
||||
.addComponent(contactsDataLabel)
|
||||
.addComponent(callLogsDataLabel)
|
||||
.addComponent(messagesDataLabel)
|
||||
.addComponent(attachmentsDataLabel))
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addComponent(messagesDataLabel))
|
||||
.addContainerGap(959, Short.MAX_VALUE))
|
||||
);
|
||||
countsPanelLayout.setVerticalGroup(
|
||||
countsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(countsPanelLayout.createSequentialGroup()
|
||||
.addGap(7, 7, 7)
|
||||
.addGroup(countsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(attachmentsLabel)
|
||||
.addComponent(attachmentsDataLabel))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(countsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(messagesLabel)
|
||||
.addComponent(messagesDataLabel))
|
||||
@ -257,40 +251,38 @@ public class SummaryViewer extends javax.swing.JPanel implements RelationshipsVi
|
||||
.addComponent(contactsDataLabel))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(countsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(emailLabel)
|
||||
.addComponent(emailDataLabel))
|
||||
.addComponent(attachmentsLabel)
|
||||
.addComponent(attachmentsDataLabel))
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
|
||||
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;
|
||||
add(countsPanel, gridBagConstraints);
|
||||
|
||||
fileReferencesPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(SummaryViewer.class, "SummaryViewer.fileReferencesPanel.border.title"))); // NOI18N
|
||||
fileReferencesPanel.setPreferredSize(new java.awt.Dimension(472, 300));
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
add(fileReferencesPanel, gridBagConstraints);
|
||||
|
||||
caseReferencesPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(SummaryViewer.class, "SummaryViewer.caseReferencesPanel.border.title"))); // NOI18N
|
||||
caseReferencesPanel.setPreferredSize(new java.awt.Dimension(472, 300));
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(countsPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(fileReferencesPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 485, Short.MAX_VALUE)
|
||||
.addComponent(caseReferencesPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addContainerGap())
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(countsPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(fileReferencesPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(caseReferencesPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 2;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
add(caseReferencesPanel, gridBagConstraints);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
|
||||
@ -303,8 +295,6 @@ public class SummaryViewer extends javax.swing.JPanel implements RelationshipsVi
|
||||
private javax.swing.JLabel contactsDataLabel;
|
||||
private javax.swing.JLabel contactsLabel;
|
||||
private javax.swing.JPanel countsPanel;
|
||||
private javax.swing.JLabel emailDataLabel;
|
||||
private javax.swing.JLabel emailLabel;
|
||||
private org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel fileReferencesPanel;
|
||||
private javax.swing.JLabel messagesDataLabel;
|
||||
private javax.swing.JLabel messagesLabel;
|
||||
|
@ -0,0 +1,347 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> 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.communications.relationships;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.Action;
|
||||
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.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.datamodel.NodeProperty;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* ChildFactory that creates createKeys and nodes from a given selectionInfo for
|
||||
* only emails, call logs and messages.
|
||||
*
|
||||
*/
|
||||
final class ThreadChildNodeFactory extends ChildFactory<BlackboardArtifact> {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ThreadChildNodeFactory.class.getName());
|
||||
|
||||
private SelectionInfo selectionInfo;
|
||||
|
||||
private final Action preferredAction;
|
||||
|
||||
/**
|
||||
* Construct a new ThreadChildNodeFactory from the currently selectionInfo
|
||||
*
|
||||
* @param preferredAction SelectionInfo object for the currently selected
|
||||
* accounts
|
||||
*/
|
||||
|
||||
ThreadChildNodeFactory(Action preferredAction) {
|
||||
this.preferredAction = preferredAction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the current instance of selectionInfo and calls the refresh method.
|
||||
*
|
||||
* @param selectionInfo New instance of the currently selected accounts
|
||||
*/
|
||||
public void refresh(SelectionInfo selectionInfo) {
|
||||
this.selectionInfo = selectionInfo;
|
||||
refresh(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a list of Keys (BlackboardArtifact) for only messages for the
|
||||
* currently selected accounts.
|
||||
*
|
||||
* @param list List of BlackboardArtifact to populate
|
||||
*
|
||||
* @return True on success
|
||||
*/
|
||||
@Override
|
||||
protected boolean createKeys(List<BlackboardArtifact> list) {
|
||||
if(selectionInfo == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
final Set<Content> relationshipSources = selectionInfo.getRelationshipSources();
|
||||
createRootMessageKeys(list, relationshipSources) ;
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to load relationship sources.", ex); //NON-NLS
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds only BlackboardArtifact objects to the list where are the earliest
|
||||
* message in a message thread (based on threadID). If there are "unthreaded"
|
||||
* messages (messages that do not have a threadID) one representitive artifact
|
||||
* will be added to the list and dealt with a node creation time.
|
||||
*
|
||||
* @param list List to populate with BlackboardArtifact keys
|
||||
* @param relationshipSources Set of Content objects
|
||||
* @return True on success
|
||||
* @throws TskCoreException
|
||||
*/
|
||||
private boolean createRootMessageKeys(List<BlackboardArtifact> list, Set<Content> relationshipSources) throws TskCoreException{
|
||||
Map<String, BlackboardArtifact> rootMessageMap = new HashMap<>();
|
||||
for(Content content: relationshipSources) {
|
||||
if(!(content instanceof BlackboardArtifact)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BlackboardArtifact bba = (BlackboardArtifact) content;
|
||||
BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(bba.getArtifactTypeID());
|
||||
|
||||
if (fromID == BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG
|
||||
|| fromID == BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG
|
||||
|| fromID == BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE) {
|
||||
|
||||
// We want email and message artifacts that do not have "threadIDs" to appear as one thread in the UI
|
||||
// To achive this assign any artifact that does not have a threadID
|
||||
// the "UNTHREADED_ID"
|
||||
// All call logs will default to a single call logs thread
|
||||
String threadID;
|
||||
if (fromID == BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG) {
|
||||
threadID = MessageNode.CALL_LOG_ID;
|
||||
} else {
|
||||
threadID = MessageNode.UNTHREADED_ID;
|
||||
}
|
||||
BlackboardAttribute attribute = bba.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_THREAD_ID));
|
||||
|
||||
if(attribute != null) {
|
||||
threadID = attribute.getValueString();
|
||||
}
|
||||
|
||||
BlackboardArtifact tableArtifact = rootMessageMap.get(threadID);
|
||||
if(tableArtifact == null) {
|
||||
rootMessageMap.put(threadID, bba);
|
||||
} else {
|
||||
// Get the date of the message
|
||||
BlackboardAttribute tableAttribute = null;
|
||||
switch(fromID) {
|
||||
case TSK_EMAIL_MSG:
|
||||
tableAttribute = tableArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT));
|
||||
attribute = bba.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT));
|
||||
// put the earliest message into the table
|
||||
if(tableAttribute != null
|
||||
&& attribute != null
|
||||
&& tableAttribute.getValueLong() > attribute.getValueLong()) {
|
||||
rootMessageMap.put(threadID, bba);
|
||||
}
|
||||
break;
|
||||
case TSK_MESSAGE:
|
||||
tableAttribute = tableArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME));
|
||||
attribute = bba.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME));
|
||||
// put the earliest message into the table
|
||||
if(tableAttribute != null
|
||||
&& attribute != null
|
||||
&& tableAttribute.getValueLong() < attribute.getValueLong()) {
|
||||
rootMessageMap.put(threadID, bba);
|
||||
}
|
||||
break;
|
||||
case TSK_CALLLOG:
|
||||
tableAttribute = tableArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START));
|
||||
attribute = bba.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START));
|
||||
// put the earliest message into the table
|
||||
if(tableAttribute != null
|
||||
&& attribute != null
|
||||
&& tableAttribute.getValueLong() > attribute.getValueLong()) {
|
||||
rootMessageMap.put(threadID, bba);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(BlackboardArtifact bba: rootMessageMap.values()) {
|
||||
list.add(bba);
|
||||
}
|
||||
|
||||
list.sort(new ThreadDateComparator());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node createNodeForKey(BlackboardArtifact bba) {
|
||||
BlackboardAttribute attribute = null;
|
||||
try {
|
||||
attribute = bba.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_THREAD_ID));
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, String.format("Unable to get threadID for artifact: %s", bba.getName()), ex);
|
||||
}
|
||||
|
||||
if (attribute != null) {
|
||||
return new ThreadNode(bba, attribute.getValueString(), preferredAction);
|
||||
} else {
|
||||
if (bba.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG.getTypeID()) {
|
||||
return new CallLogNode();
|
||||
} else {
|
||||
// Only one of these should occur.
|
||||
return new UnthreadedNode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This node represents the "call log" thread.
|
||||
*/
|
||||
final class CallLogNode extends AbstractNode {
|
||||
/**
|
||||
* Construct an instance of a CallLogNode.
|
||||
*/
|
||||
CallLogNode() {
|
||||
super(Children.LEAF);
|
||||
setDisplayName("Call Logs");
|
||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/communications/images/unthreaded.png" );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Sheet createSheet() {
|
||||
Sheet sheet = super.createSheet();
|
||||
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
|
||||
if (sheetSet == null) {
|
||||
sheetSet = Sheet.createPropertiesSet();
|
||||
sheet.put(sheetSet);
|
||||
}
|
||||
|
||||
// Give this node a threadID of "CALL_LOG_ID"
|
||||
sheetSet.put(new NodeProperty<>("ThreadID", "ThreadID","",MessageNode.CALL_LOG_ID));
|
||||
|
||||
return sheet;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This node represents the "unthreaded" thread.
|
||||
*/
|
||||
final class UnthreadedNode extends AbstractNode {
|
||||
/**
|
||||
* Construct an instance of UnthreadNode.
|
||||
*/
|
||||
UnthreadedNode() {
|
||||
super(Children.LEAF);
|
||||
setDisplayName("Unthreaded");
|
||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/communications/images/unthreaded.png" );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Sheet createSheet() {
|
||||
Sheet sheet = super.createSheet();
|
||||
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
|
||||
if (sheetSet == null) {
|
||||
sheetSet = Sheet.createPropertiesSet();
|
||||
sheet.put(sheetSet);
|
||||
}
|
||||
|
||||
// Give this node a threadID of "UNTHEADED_ID"
|
||||
sheetSet.put(new NodeProperty<>("ThreadID", "ThreadID","",MessageNode.UNTHREADED_ID));
|
||||
|
||||
return sheet;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A comparator class for comparing BlackboardArtifacts of type
|
||||
* TSK_EMAIL_MSG, TSK_MESSAGE, and TSK_CALLLOG by their respective creation
|
||||
* date-time.
|
||||
*
|
||||
* Nodes will be sorted newest to oldest.
|
||||
*/
|
||||
class ThreadDateComparator implements Comparator<BlackboardArtifact> {
|
||||
|
||||
@Override
|
||||
public int compare(BlackboardArtifact bba1, BlackboardArtifact bba2) {
|
||||
BlackboardAttribute attribute1 = null;
|
||||
BlackboardAttribute attribute2 = null;
|
||||
// Inializing to Long.MAX_VALUE so that if a BlackboardArtifact of
|
||||
// any unexpected type is passed in, it will bubble to the top of
|
||||
// the list.
|
||||
long dateTime1 = Long.MAX_VALUE;
|
||||
long dateTime2 = Long.MAX_VALUE;
|
||||
|
||||
if (bba1 != null) {
|
||||
BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(bba1.getArtifactTypeID());
|
||||
if (fromID != null) {
|
||||
try {
|
||||
switch (fromID) {
|
||||
case TSK_EMAIL_MSG:
|
||||
attribute1 = bba1.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT));
|
||||
|
||||
break;
|
||||
case TSK_MESSAGE:
|
||||
attribute1 = bba1.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME));
|
||||
|
||||
break;
|
||||
case TSK_CALLLOG:
|
||||
attribute1 = bba1.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START));
|
||||
|
||||
break;
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, String.format("Unable to compare attributes for artifact %d", bba1.getArtifactID()), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bba1 != null) {
|
||||
BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(bba2.getArtifactTypeID());
|
||||
if (fromID != null) {
|
||||
try {
|
||||
switch (fromID) {
|
||||
case TSK_EMAIL_MSG:
|
||||
attribute2 = bba2.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT));
|
||||
break;
|
||||
case TSK_MESSAGE:
|
||||
attribute2 = bba2.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME));
|
||||
break;
|
||||
case TSK_CALLLOG:
|
||||
attribute2 = bba2.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START));
|
||||
break;
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, String.format("Unable to compare attributes for artifact %d", bba2.getArtifactID()), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (attribute1 != null) {
|
||||
dateTime1 = attribute1.getValueLong();
|
||||
}
|
||||
|
||||
if (attribute2 != null) {
|
||||
dateTime2 = attribute2.getValueLong();
|
||||
}
|
||||
|
||||
return Long.compare(dateTime1, dateTime2) * -1;
|
||||
}
|
||||
}
|
||||
}
|
100
Core/src/org/sleuthkit/autopsy/communications/relationships/ThreadNode.java
Executable file
100
Core/src/org/sleuthkit/autopsy/communications/relationships/ThreadNode.java
Executable file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> 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.communications.relationships;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.Action;
|
||||
import org.openide.nodes.AbstractNode;
|
||||
import org.openide.nodes.Children;
|
||||
import org.openide.nodes.Sheet;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.datamodel.NodeProperty;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* An AbstractNode subclass which wraps a MessageNode object. Doing this allows
|
||||
* for the reuse of the createSheet and other function from MessageNode, but
|
||||
* also some customizing of how a ThreadNode is shown.
|
||||
*/
|
||||
final class ThreadNode extends AbstractNode{
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ThreadNode.class.getName());
|
||||
|
||||
private final static int MAX_SUBJECT_LENGTH = 120;
|
||||
|
||||
final private MessageNode messageNode;
|
||||
|
||||
ThreadNode(BlackboardArtifact artifact, String threadID, Action preferredAction) {
|
||||
super(Children.LEAF);
|
||||
messageNode = new MessageNode(artifact, threadID, preferredAction);
|
||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/communications/images/threaded.png" );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Sheet createSheet() {
|
||||
BlackboardArtifact artifact = messageNode.getArtifact();
|
||||
if(artifact == null) {
|
||||
return messageNode.createSheet() ;
|
||||
}
|
||||
|
||||
Sheet sheet = messageNode.createSheet();
|
||||
BlackboardArtifact.ARTIFACT_TYPE artifactTypeID = BlackboardArtifact.ARTIFACT_TYPE.fromID(artifact.getArtifactTypeID());
|
||||
|
||||
// If its a text message, replace the subject node which is probably
|
||||
// an empty string with the firest 120 characters of the text message
|
||||
if(artifactTypeID != null && artifactTypeID == TSK_MESSAGE) {
|
||||
try {
|
||||
BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.fromID(TSK_TEXT.getTypeID())));
|
||||
if(attribute != null) {
|
||||
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
|
||||
sheetSet.remove("Subject");
|
||||
|
||||
String msg = attribute.getDisplayString();
|
||||
if(msg != null && msg.length() > MAX_SUBJECT_LENGTH) {
|
||||
msg = msg.substring(0, MAX_SUBJECT_LENGTH) + "...";
|
||||
}
|
||||
|
||||
sheetSet.put(new NodeProperty<>("Subject", Bundle.MessageNode_Node_Property_Subject(), "", msg)); //NON-NLS
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, String.format("Unable to get the text message from message artifact %d", artifact.getId()), ex);
|
||||
}
|
||||
}
|
||||
|
||||
return sheet;
|
||||
}
|
||||
|
||||
String getThreadID() {
|
||||
return messageNode.getThreadID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Action getPreferredAction() {
|
||||
return messageNode.getPreferredAction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return messageNode.getDisplayName();
|
||||
}
|
||||
}
|
@ -83,9 +83,10 @@ MediaViewImagePanel.zoomResetButton.text=Reset
|
||||
MediaViewImagePanel.zoomTextField.text=
|
||||
MediaViewImagePanel.rotationTextField.text=
|
||||
MediaViewImagePanel.rotateLeftButton.toolTipText=
|
||||
HtmlPanel.showImagesToggleButton.text=Show Images
|
||||
HtmlPanel.showImagesToggleButton.text=Download Images
|
||||
MediaPlayerPanel.audioSlider.toolTipText=
|
||||
MediaPlayerPanel.VolumeIcon.text=\ \ \ \ \ Volume
|
||||
MediaPlayerPanel.progressLabel.text=00:00:00/00:00:00
|
||||
MediaPlayerPanel.playButton.text=\u25ba
|
||||
MediaPlayerPanel.infoLabel.text=No Errors
|
||||
MediaViewImagePanel.tagsMenu.text_1=Tags Menu
|
||||
|
@ -22,7 +22,7 @@ GstVideoPanel.cannotProcFile.err=The media player cannot process this file.
|
||||
GstVideoPanel.noOpenCase.errMsg=No open case available.
|
||||
Html_text_display_error=The HTML text cannot be displayed, it may not be correctly formed HTML.
|
||||
HtmlPanel_showImagesToggleButton_hide=Hide Images
|
||||
HtmlPanel_showImagesToggleButton_show=Show Images
|
||||
HtmlPanel_showImagesToggleButton_show=Download Images
|
||||
HtmlViewer_file_error=This file is missing or unreadable.
|
||||
MediaFileViewer.initGst.gstException.msg=Error initializing gstreamer for audio/video viewing and frame extraction capabilities. Video and audio viewing will be disabled.
|
||||
GstVideoPanel.setupVideo.infoLabel.text=Playback of deleted videos is not supported, use an external player.
|
||||
@ -42,9 +42,17 @@ MediaFileViewer.toolTip=Displays supported multimedia files (images, videos, aud
|
||||
MediaPlayerPanel.noSupport=File not supported.
|
||||
MediaPlayerPanel.timeFormat=%02d:%02d:%02d
|
||||
MediaPlayerPanel.unknownTime=Unknown
|
||||
MediaViewImagePanel.createTagOption=Create
|
||||
MediaViewImagePanel.deleteTagOption=Delete
|
||||
MediaViewImagePanel.errorLabel.OOMText=Could not load file into Media View: insufficent memory.
|
||||
MediaViewImagePanel.errorLabel.text=Could not load file into Media View.
|
||||
MediaViewImagePanel.exportSaveText=Save
|
||||
MediaViewImagePanel.exportTagOption=Export
|
||||
MediaViewImagePanel.externalViewerButton.text=Open in External Viewer Ctrl+E
|
||||
MediaViewImagePanel.fileChooserTitle=Choose a save location
|
||||
MediaViewImagePanel.hideTagOption=Hide
|
||||
MediaViewImagePanel.successfulExport=Tagged image was successfully saved.
|
||||
MediaViewImagePanel.unsuccessfulExport=Unable to export tagged image to disk.
|
||||
MediaViewVideoPanel.pauseButton.text=\u25ba
|
||||
MediaViewVideoPanel.progressLabel.text=00:00
|
||||
MediaViewVideoPanel.infoLabel.text=info
|
||||
@ -145,12 +153,13 @@ MediaViewImagePanel.zoomResetButton.text=Reset
|
||||
MediaViewImagePanel.zoomTextField.text=
|
||||
MediaViewImagePanel.rotationTextField.text=
|
||||
MediaViewImagePanel.rotateLeftButton.toolTipText=
|
||||
HtmlPanel.showImagesToggleButton.text=Show Images
|
||||
HtmlPanel.showImagesToggleButton.text=Download Images
|
||||
MediaPlayerPanel.audioSlider.toolTipText=
|
||||
MediaPlayerPanel.VolumeIcon.text=\ \ \ \ \ Volume
|
||||
MediaPlayerPanel.progressLabel.text=00:00:00/00:00:00
|
||||
MediaPlayerPanel.playButton.text=\u25ba
|
||||
MediaPlayerPanel.infoLabel.text=No Errors
|
||||
MediaViewImagePanel.tagsMenu.text_1=Tags Menu
|
||||
# {0} - tableName
|
||||
SQLiteViewer.readTable.errorText=Error getting rows for table: {0}
|
||||
# {0} - tableName
|
||||
|
@ -77,12 +77,12 @@ public class FileViewer extends javax.swing.JPanel implements DataContentViewer
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the FileTypeViewer for a given mimetype
|
||||
* Get the FileTypeViewer for a given file
|
||||
*
|
||||
* @param mimeType
|
||||
* @param file
|
||||
*
|
||||
* @return FileTypeViewer, null if no known content viewer supports the
|
||||
* mimetype
|
||||
* file
|
||||
*/
|
||||
private FileTypeViewer getSupportingViewer(AbstractFile file) {
|
||||
FileTypeViewer viewer = mimeTypeToViewerMap.get(file.getMIMEType());
|
||||
@ -143,7 +143,7 @@ public class FileViewer extends javax.swing.JPanel implements DataContentViewer
|
||||
viewer.setFile(file);
|
||||
this.removeAll();
|
||||
this.add(viewer.getComponent());
|
||||
this.repaint();
|
||||
this.validate();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="showImagesToggleButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="95" max="32767" attributes="0"/>
|
||||
<EmptySpace min="0" pref="75" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="htmlJPanel" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
|
@ -18,6 +18,11 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.contentviewers;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
@ -25,8 +30,9 @@ import javafx.concurrent.Worker;
|
||||
import javafx.scene.web.WebView;
|
||||
import javafx.embed.swing.JFXPanel;
|
||||
import javafx.scene.Scene;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Node;
|
||||
import net.htmlparser.jericho.Attribute;
|
||||
import net.htmlparser.jericho.OutputDocument;
|
||||
import net.htmlparser.jericho.Source;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.NodeList;
|
||||
@ -38,6 +44,7 @@ import org.w3c.dom.events.EventTarget;
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
final class HtmlPanel extends javax.swing.JPanel {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(HtmlPanel.class.getName());
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String TEXT_TYPE = "text/plain";
|
||||
private final JFXPanel jfxPanel = new JFXPanel();
|
||||
@ -92,26 +99,76 @@ final class HtmlPanel extends javax.swing.JPanel {
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans out input HTML string
|
||||
* Cleans out input HTML string so it will not access resources over the internet
|
||||
*
|
||||
* @param htmlInString The HTML string to cleanse
|
||||
*
|
||||
* @return The cleansed HTML String
|
||||
*/
|
||||
private String cleanseHTML(String htmlInString) {
|
||||
org.jsoup.nodes.Document doc = Jsoup.parse(htmlInString);
|
||||
// remove all 'img' tags.
|
||||
doc.select("img").stream().forEach(Node::remove);
|
||||
// remove all 'span' tags, these are often images which are ads
|
||||
doc.select("span").stream().forEach(Node::remove);
|
||||
return doc.html();
|
||||
String returnString = "";
|
||||
try {
|
||||
Source source = new Source(new StringReader(htmlInString));
|
||||
OutputDocument document = new OutputDocument(source);
|
||||
//remove background images
|
||||
source.getAllTags().stream().filter((tag) -> (tag.toString().contains("background-image"))).forEachOrdered((tag) -> {
|
||||
document.remove(tag);
|
||||
});
|
||||
//remove images
|
||||
source.getAllElements("img").forEach((element) -> {
|
||||
document.remove(element.getAllTags());
|
||||
});
|
||||
//remove frames
|
||||
source.getAllElements("frame").forEach((element) -> {
|
||||
document.remove(element.getAllTags());
|
||||
});
|
||||
//remove iframes
|
||||
source.getAllElements("iframe").forEach((element) -> {
|
||||
document.remove(element.getAllTags());
|
||||
});
|
||||
//remove pictures
|
||||
source.getAllElements("picture").forEach((element) -> {
|
||||
document.remove(element.getAllTags());
|
||||
});
|
||||
//remove svg
|
||||
source.getAllElements("svg").forEach((element) -> {
|
||||
document.remove(element.getAllTags());
|
||||
});
|
||||
//remove audio
|
||||
source.getAllElements("audio").forEach((element) -> {
|
||||
document.remove(element.getAllTags());
|
||||
});
|
||||
//remove video
|
||||
source.getAllElements("video").forEach((element) -> {
|
||||
document.remove(element.getAllTags());
|
||||
});
|
||||
//remove tracks
|
||||
source.getAllElements("track").forEach((element) -> {
|
||||
document.remove(element.getAllTags());
|
||||
});
|
||||
//remove embeded external elements
|
||||
source.getAllElements("embed").forEach((element) -> {
|
||||
document.remove(element.getAllTags());
|
||||
});
|
||||
//remove linked elements
|
||||
source.getAllElements("link").forEach((element) -> {
|
||||
document.remove(element.getAllTags());
|
||||
});
|
||||
//remove other URI elements such as input boxes
|
||||
List<Attribute> attributesToRemove = source.getURIAttributes();
|
||||
document.remove(attributesToRemove);
|
||||
returnString = document.toString();
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.WARNING, "Unable to read html for cleaning out URI elements with Jericho", ex);
|
||||
}
|
||||
return returnString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the panel to reflect the current show/hide images setting.
|
||||
*/
|
||||
@Messages({
|
||||
"HtmlPanel_showImagesToggleButton_show=Show Images",
|
||||
"HtmlPanel_showImagesToggleButton_show=Download Images",
|
||||
"HtmlPanel_showImagesToggleButton_hide=Hide Images",
|
||||
"Html_text_display_error=The HTML text cannot be displayed, it may not be correctly formed HTML.",})
|
||||
private void refresh() {
|
||||
@ -164,7 +221,7 @@ final class HtmlPanel extends javax.swing.JPanel {
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(showImagesToggleButton)
|
||||
.addGap(0, 95, Short.MAX_VALUE))
|
||||
.addGap(0, 75, Short.MAX_VALUE))
|
||||
.addComponent(htmlJPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
|
@ -11,30 +11,8 @@
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="htmlPanel" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="htmlPanel" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="org.sleuthkit.autopsy.contentviewers.HtmlPanel" name="htmlPanel">
|
||||
</Component>
|
||||
</SubComponents>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
|
||||
</Form>
|
||||
|
@ -37,17 +37,18 @@ final class HtmlViewer extends javax.swing.JPanel implements FileTypeViewer {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger logger = Logger.getLogger(HtmlViewer.class.getName());
|
||||
|
||||
private static final String[] SUPPORTED_MIMETYPES = new String[]{
|
||||
"text/html",
|
||||
"application/xhtml+xml"
|
||||
};
|
||||
private final org.sleuthkit.autopsy.contentviewers.HtmlPanel htmlPanel = new org.sleuthkit.autopsy.contentviewers.HtmlPanel();
|
||||
|
||||
/**
|
||||
* Creates new form HtmlViewerPanel
|
||||
*/
|
||||
HtmlViewer() {
|
||||
initComponents();
|
||||
this.add(htmlPanel);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -81,31 +82,12 @@ final class HtmlViewer extends javax.swing.JPanel implements FileTypeViewer {
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
|
||||
htmlPanel = new org.sleuthkit.autopsy.contentviewers.HtmlPanel();
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(htmlPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addContainerGap())
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(htmlPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addContainerGap())
|
||||
);
|
||||
setLayout(new java.awt.BorderLayout());
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private org.sleuthkit.autopsy.contentviewers.HtmlPanel htmlPanel;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
@Override
|
||||
public List<String> getSupportedMIMETypes() {
|
||||
return Arrays.asList(SUPPORTED_MIMETYPES);
|
||||
|
@ -19,7 +19,7 @@
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,100,0,0,3,117"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout">
|
||||
@ -200,6 +200,44 @@
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="zoomResetButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.Box$Filler" name="filler1">
|
||||
</Component>
|
||||
<Component class="javax.swing.Box$Filler" name="filler2">
|
||||
<Properties>
|
||||
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[32767, 0]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.HorizontalGlue"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Container class="javax.swing.JPanel" name="jPanel1">
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignFlowLayout"/>
|
||||
</Container>
|
||||
<Component class="javax.swing.JButton" name="tagsMenu">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/contentviewers/Bundle.properties" key="MediaViewImagePanel.tagsMenu.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="focusable" type="boolean" value="false"/>
|
||||
<Property name="horizontalTextPosition" type="int" value="0"/>
|
||||
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[75, 21]"/>
|
||||
</Property>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[75, 21]"/>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[75, 21]"/>
|
||||
</Property>
|
||||
<Property name="verticalTextPosition" type="int" value="3"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="tagsMenuMousePressed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
|
@ -20,18 +20,30 @@ package org.sleuthkit.autopsy.contentviewers;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import static java.util.Objects.nonNull;
|
||||
import java.util.SortedSet;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
import javafx.application.Platform;
|
||||
import javafx.collections.ListChangeListener.Change;
|
||||
import javafx.concurrent.Task;
|
||||
import javafx.embed.swing.JFXPanel;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.geometry.Rectangle2D;
|
||||
import javafx.scene.Cursor;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
@ -45,19 +57,41 @@ import javafx.scene.transform.Rotate;
|
||||
import javafx.scene.transform.Scale;
|
||||
import javafx.scene.transform.Translate;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.JFileChooser;
|
||||
import javafx.scene.Node;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.JSeparator;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.SwingWorker;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.controlsfx.control.MaskerPane;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.python.google.common.collect.Lists;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.shape.Rectangle;
|
||||
import org.sleuthkit.autopsy.actions.GetTagNameAndCommentDialog;
|
||||
import org.sleuthkit.autopsy.actions.GetTagNameAndCommentDialog.TagNameAndComment;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.casemodule.services.contentviewertags.ContentViewerTagManager;
|
||||
import org.sleuthkit.autopsy.casemodule.services.contentviewertags.ContentViewerTagManager.ContentViewerTag;
|
||||
import org.sleuthkit.autopsy.casemodule.services.contentviewertags.ContentViewerTagManager.SerializationException;
|
||||
import org.sleuthkit.autopsy.contentviewers.imagetagging.ImageTagsUtil;
|
||||
import org.sleuthkit.autopsy.contentviewers.imagetagging.ImageTagControls;
|
||||
import org.sleuthkit.autopsy.contentviewers.imagetagging.ImageTagRegion;
|
||||
import org.sleuthkit.autopsy.contentviewers.imagetagging.ImageTagCreator;
|
||||
import org.sleuthkit.autopsy.contentviewers.imagetagging.ImageTag;
|
||||
import org.sleuthkit.autopsy.contentviewers.imagetagging.ImageTagsGroup;
|
||||
import org.sleuthkit.autopsy.corelibs.OpenCvLoader;
|
||||
import org.sleuthkit.autopsy.coreutils.ImageUtils;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
||||
import org.sleuthkit.autopsy.datamodel.FileNode;
|
||||
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.ContentTag;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* Image viewer part of the Media View layered pane. Uses JavaFX to display the
|
||||
@ -70,17 +104,30 @@ import org.sleuthkit.datamodel.AbstractFile;
|
||||
class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPanel {
|
||||
|
||||
private static final Image EXTERNAL = new Image(MediaViewImagePanel.class.getResource("/org/sleuthkit/autopsy/images/external.png").toExternalForm());
|
||||
private final static Logger LOGGER = Logger.getLogger(MediaViewImagePanel.class.getName());
|
||||
|
||||
private final boolean fxInited;
|
||||
|
||||
private JFXPanel fxPanel;
|
||||
private Group imageGroup;
|
||||
private ImageTaggingTool tagger;
|
||||
private AbstractFile file;
|
||||
private Group masterGroup;
|
||||
private ImageTagsGroup tagsGroup;
|
||||
private ImageTagCreator imageTagCreator;
|
||||
private ImageView fxImageView;
|
||||
private ScrollPane scrollPane;
|
||||
private final ProgressBar progressBar = new ProgressBar();
|
||||
private final MaskerPane maskerPane = new MaskerPane();
|
||||
|
||||
private final JPopupMenu imageTaggingOptions = new JPopupMenu();
|
||||
private final JMenuItem createTagMenuItem;
|
||||
private final JMenuItem deleteTagMenuItem;
|
||||
private final JMenuItem hideTagsMenuItem;
|
||||
private final JMenuItem exportTagsMenuItem;
|
||||
|
||||
private final JFileChooser exportChooser;
|
||||
|
||||
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
|
||||
|
||||
private double zoomRatio;
|
||||
private double rotation; // Can be 0, 90, 180, and 270.
|
||||
|
||||
@ -113,36 +160,178 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan
|
||||
/**
|
||||
* Creates new form MediaViewImagePanel
|
||||
*/
|
||||
@NbBundle.Messages({
|
||||
"MediaViewImagePanel.createTagOption=Create",
|
||||
"MediaViewImagePanel.deleteTagOption=Delete",
|
||||
"MediaViewImagePanel.hideTagOption=Hide",
|
||||
"MediaViewImagePanel.exportTagOption=Export"
|
||||
})
|
||||
public MediaViewImagePanel() {
|
||||
initComponents();
|
||||
fxInited = org.sleuthkit.autopsy.core.Installer.isJavaFxInited();
|
||||
|
||||
exportChooser = new JFileChooser();
|
||||
exportChooser.setDialogTitle(Bundle.MediaViewImagePanel_fileChooserTitle());
|
||||
|
||||
//Build popupMenu when Tags Menu button is pressed.
|
||||
createTagMenuItem = new JMenuItem(Bundle.MediaViewImagePanel_createTagOption());
|
||||
createTagMenuItem.addActionListener((event) -> createTag());
|
||||
imageTaggingOptions.add(createTagMenuItem);
|
||||
|
||||
imageTaggingOptions.add(new JSeparator());
|
||||
|
||||
deleteTagMenuItem = new JMenuItem(Bundle.MediaViewImagePanel_deleteTagOption());
|
||||
deleteTagMenuItem.addActionListener((event) -> deleteTag());
|
||||
imageTaggingOptions.add(deleteTagMenuItem);
|
||||
|
||||
imageTaggingOptions.add(new JSeparator());
|
||||
|
||||
hideTagsMenuItem = new JMenuItem(Bundle.MediaViewImagePanel_hideTagOption());
|
||||
hideTagsMenuItem.addActionListener((event) -> showOrHideTags());
|
||||
imageTaggingOptions.add(hideTagsMenuItem);
|
||||
|
||||
imageTaggingOptions.add(new JSeparator());
|
||||
|
||||
exportTagsMenuItem = new JMenuItem(Bundle.MediaViewImagePanel_exportTagOption());
|
||||
exportTagsMenuItem.addActionListener((event) -> exportTags());
|
||||
imageTaggingOptions.add(exportTagsMenuItem);
|
||||
|
||||
imageTaggingOptions.setPopupSize(300, 150);
|
||||
|
||||
//Disable image tagging for non-windows users or upon failure to load OpenCV.
|
||||
if (!PlatformUtil.isWindowsOS() || !OpenCvLoader.hasOpenCvLoaded()) {
|
||||
tagsMenu.setEnabled(false);
|
||||
imageTaggingOptions.setEnabled(false);
|
||||
}
|
||||
|
||||
if (fxInited) {
|
||||
Platform.runLater(() -> {
|
||||
Platform.runLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// build jfx ui (we could do this in FXML?)
|
||||
fxImageView = new ImageView(); // will hold image
|
||||
masterGroup = new Group(fxImageView);
|
||||
tagsGroup = new ImageTagsGroup(fxImageView);
|
||||
tagsGroup.getChildren().addListener((Change<? extends Node> c) -> {
|
||||
if (c.getList().isEmpty()) {
|
||||
pcs.firePropertyChange(new PropertyChangeEvent(this,
|
||||
"state", null, State.EMPTY));
|
||||
}
|
||||
});
|
||||
|
||||
// build jfx ui (we could do this in FXML?)
|
||||
fxImageView = new ImageView(); // will hold image
|
||||
imageGroup = new Group();
|
||||
imageGroup.getChildren().add(fxImageView);
|
||||
scrollPane = new ScrollPane(imageGroup); // scrolls and sizes imageview
|
||||
scrollPane.getStyleClass().add("bg"); //NOI18N
|
||||
scrollPane.setVbarPolicy(ScrollBarPolicy.AS_NEEDED);
|
||||
scrollPane.setHbarPolicy(ScrollBarPolicy.AS_NEEDED);
|
||||
subscribeTagMenuItemsToStateChanges();
|
||||
|
||||
fxPanel = new JFXPanel(); // bridge jfx-swing
|
||||
Scene scene = new Scene(scrollPane); //root of jfx tree
|
||||
scene.getStylesheets().add(MediaViewImagePanel.class.getResource("MediaViewImagePanel.css").toExternalForm()); //NOI18N
|
||||
fxPanel.setScene(scene);
|
||||
masterGroup.getChildren().add(tagsGroup);
|
||||
|
||||
fxImageView.setSmooth(true);
|
||||
fxImageView.setCache(true);
|
||||
//Update buttons when users select (or unselect) image tags.
|
||||
tagsGroup.addFocusChangeListener((event) -> {
|
||||
if (event.getPropertyName().equals(ImageTagControls.NOT_FOCUSED.getName())) {
|
||||
if (masterGroup.getChildren().contains(imageTagCreator)) {
|
||||
return;
|
||||
}
|
||||
|
||||
EventQueue.invokeLater(() -> {
|
||||
add(fxPanel);//add jfx ui to JPanel
|
||||
});
|
||||
if (tagsGroup.getChildren().isEmpty()) {
|
||||
pcs.firePropertyChange(new PropertyChangeEvent(this,
|
||||
"state", null, State.EMPTY));
|
||||
} else {
|
||||
pcs.firePropertyChange(new PropertyChangeEvent(this,
|
||||
"state", null, State.CREATE));
|
||||
}
|
||||
} else if (event.getPropertyName().equals(ImageTagControls.FOCUSED.getName())) {
|
||||
pcs.firePropertyChange(new PropertyChangeEvent(this,
|
||||
"state", null, State.SELECTED));
|
||||
}
|
||||
});
|
||||
|
||||
scrollPane = new ScrollPane(masterGroup); // scrolls and sizes imageview
|
||||
scrollPane.getStyleClass().add("bg"); //NOI18N
|
||||
scrollPane.setVbarPolicy(ScrollBarPolicy.AS_NEEDED);
|
||||
scrollPane.setHbarPolicy(ScrollBarPolicy.AS_NEEDED);
|
||||
|
||||
fxPanel = new JFXPanel(); // bridge jfx-swing
|
||||
Scene scene = new Scene(scrollPane); //root of jfx tree
|
||||
scene.getStylesheets().add(MediaViewImagePanel.class.getResource("MediaViewImagePanel.css").toExternalForm()); //NOI18N
|
||||
fxPanel.setScene(scene);
|
||||
|
||||
fxImageView.setSmooth(true);
|
||||
fxImageView.setCache(true);
|
||||
|
||||
EventQueue.invokeLater(() -> {
|
||||
add(fxPanel);//add jfx ui to JPanel
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle tags menu item enabling and disabling given the state of the
|
||||
* content viewer. For example, when the tags group is empty (no tags on image),
|
||||
* disable delete menu item, hide menu item, and export menu item.
|
||||
*/
|
||||
private void subscribeTagMenuItemsToStateChanges() {
|
||||
pcs.addPropertyChangeListener((event) -> {
|
||||
State currentState = (State) event.getNewValue();
|
||||
switch (currentState) {
|
||||
case CREATE:
|
||||
createTagMenuItem.setEnabled(true);
|
||||
deleteTagMenuItem.setEnabled(false);
|
||||
hideTagsMenuItem.setEnabled(true);
|
||||
exportTagsMenuItem.setEnabled(true);
|
||||
break;
|
||||
case SELECTED:
|
||||
if (masterGroup.getChildren().contains(imageTagCreator)) {
|
||||
imageTagCreator.disconnect();
|
||||
masterGroup.getChildren().remove(imageTagCreator);
|
||||
}
|
||||
createTagMenuItem.setEnabled(false);
|
||||
deleteTagMenuItem.setEnabled(true);
|
||||
hideTagsMenuItem.setEnabled(true);
|
||||
exportTagsMenuItem.setEnabled(true);
|
||||
break;
|
||||
case HIDDEN:
|
||||
createTagMenuItem.setEnabled(false);
|
||||
deleteTagMenuItem.setEnabled(false);
|
||||
hideTagsMenuItem.setEnabled(true);
|
||||
hideTagsMenuItem.setText(DisplayOptions.SHOW_TAGS.getName());
|
||||
exportTagsMenuItem.setEnabled(false);
|
||||
break;
|
||||
case VISIBLE:
|
||||
createTagMenuItem.setEnabled(true);
|
||||
deleteTagMenuItem.setEnabled(false);
|
||||
hideTagsMenuItem.setEnabled(true);
|
||||
hideTagsMenuItem.setText(DisplayOptions.HIDE_TAGS.getName());
|
||||
exportTagsMenuItem.setEnabled(true);
|
||||
break;
|
||||
case DEFAULT:
|
||||
case EMPTY:
|
||||
if (masterGroup.getChildren().contains(imageTagCreator)) {
|
||||
imageTagCreator.disconnect();
|
||||
}
|
||||
createTagMenuItem.setEnabled(true);
|
||||
deleteTagMenuItem.setEnabled(false);
|
||||
hideTagsMenuItem.setEnabled(false);
|
||||
hideTagsMenuItem.setText(DisplayOptions.HIDE_TAGS.getName());
|
||||
exportTagsMenuItem.setEnabled(false);
|
||||
break;
|
||||
case NONEMPTY:
|
||||
createTagMenuItem.setEnabled(true);
|
||||
deleteTagMenuItem.setEnabled(false);
|
||||
hideTagsMenuItem.setEnabled(true);
|
||||
exportTagsMenuItem.setEnabled(true);
|
||||
break;
|
||||
case DISABLE:
|
||||
createTagMenuItem.setEnabled(false);
|
||||
deleteTagMenuItem.setEnabled(false);
|
||||
hideTagsMenuItem.setEnabled(false);
|
||||
exportTagsMenuItem.setEnabled(false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean isInited() {
|
||||
return fxInited;
|
||||
}
|
||||
@ -154,10 +343,11 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan
|
||||
Platform.runLater(() -> {
|
||||
fxImageView.setViewport(new Rectangle2D(0, 0, 0, 0));
|
||||
fxImageView.setImage(null);
|
||||
tagger.defaultSettings();
|
||||
|
||||
pcs.firePropertyChange(new PropertyChangeEvent(this,
|
||||
"state", null, State.DEFAULT));
|
||||
masterGroup.getChildren().clear();
|
||||
scrollPane.setContent(null);
|
||||
scrollPane.setContent(imageGroup);
|
||||
scrollPane.setContent(masterGroup);
|
||||
});
|
||||
}
|
||||
|
||||
@ -205,14 +395,31 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan
|
||||
|
||||
try {
|
||||
Image fxImage = readImageTask.get();
|
||||
masterGroup.getChildren().clear();
|
||||
tagsGroup.getChildren().clear();
|
||||
this.file = file;
|
||||
if (nonNull(fxImage)) {
|
||||
// We have a non-null image, so let's show it.
|
||||
fxImageView.setImage(fxImage);
|
||||
imageGroup.getChildren().remove(tagger);
|
||||
tagger = new ImageTaggingTool(fxImageView, Color.RED);
|
||||
imageGroup.getChildren().add(tagger);
|
||||
resetView();
|
||||
scrollPane.setContent(imageGroup);
|
||||
masterGroup.getChildren().add(fxImageView);
|
||||
masterGroup.getChildren().add(tagsGroup);
|
||||
|
||||
try {
|
||||
List<ContentTag> tags = Case.getCurrentCase().getServices()
|
||||
.getTagsManager().getContentTagsByContent(file);
|
||||
|
||||
List<ContentViewerTag<ImageTagRegion>> contentViewerTags = getContentViewerTags(tags);
|
||||
//Add all image tags
|
||||
tagsGroup = buildImageTagsGroup(contentViewerTags);
|
||||
if (!tagsGroup.getChildren().isEmpty()) {
|
||||
pcs.firePropertyChange(new PropertyChangeEvent(this,
|
||||
"state", null, State.NONEMPTY));
|
||||
}
|
||||
} catch (TskCoreException | NoCurrentCaseException ex) {
|
||||
LOGGER.log(Level.WARNING, "Could not retrieve image tags for file in case db", ex); //NON-NLS
|
||||
}
|
||||
scrollPane.setContent(masterGroup);
|
||||
} else {
|
||||
showErrorNode(Bundle.MediaViewImagePanel_errorLabel_text(), file);
|
||||
}
|
||||
@ -252,6 +459,52 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all ContentViewerTags that are of type 'ImageTagRegion' for the
|
||||
* current file.
|
||||
*
|
||||
* @param contentTags
|
||||
* @return
|
||||
* @throws TskCoreException
|
||||
* @throws NoCurrentCaseException
|
||||
*/
|
||||
private List<ContentViewerTag<ImageTagRegion>> getContentViewerTags(List<ContentTag> contentTags)
|
||||
throws TskCoreException, NoCurrentCaseException {
|
||||
List<ContentViewerTag<ImageTagRegion>> contentViewerTags = new ArrayList<>();
|
||||
for (ContentTag contentTag : contentTags) {
|
||||
ContentViewerTag<ImageTagRegion> contentViewerTag = ContentViewerTagManager
|
||||
.getTag(contentTag, ImageTagRegion.class);
|
||||
if (contentViewerTag == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
contentViewerTags.add(contentViewerTag);
|
||||
}
|
||||
return contentViewerTags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds ImageTag instances from stored ContentViewerTags of the
|
||||
* appropriate type.
|
||||
*
|
||||
* @param contentTags
|
||||
* @return
|
||||
* @throws TskCoreException
|
||||
* @throws NoCurrentCaseException
|
||||
*/
|
||||
private ImageTagsGroup buildImageTagsGroup(List<ContentViewerTag<ImageTagRegion>> contentViewerTags) {
|
||||
|
||||
contentViewerTags.forEach(contentViewerTag -> {
|
||||
/**
|
||||
* Build the image tag, add an edit event call back to persist all
|
||||
* edits made on this image tag instance.
|
||||
*/
|
||||
tagsGroup.getChildren().add(buildImageTag(contentViewerTag));
|
||||
});
|
||||
|
||||
return tagsGroup;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return supported mime types
|
||||
*/
|
||||
@ -303,6 +556,10 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan
|
||||
zoomInButton = new javax.swing.JButton();
|
||||
jSeparator2 = new javax.swing.JToolBar.Separator();
|
||||
zoomResetButton = new javax.swing.JButton();
|
||||
filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0));
|
||||
filler2 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0));
|
||||
jPanel1 = new javax.swing.JPanel();
|
||||
tagsMenu = new javax.swing.JButton();
|
||||
|
||||
setBackground(new java.awt.Color(0, 0, 0));
|
||||
addComponentListener(new java.awt.event.ComponentAdapter() {
|
||||
@ -406,6 +663,23 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan
|
||||
}
|
||||
});
|
||||
toolbar.add(zoomResetButton);
|
||||
toolbar.add(filler1);
|
||||
toolbar.add(filler2);
|
||||
toolbar.add(jPanel1);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(tagsMenu, org.openide.util.NbBundle.getMessage(MediaViewImagePanel.class, "MediaViewImagePanel.tagsMenu.text_1")); // NOI18N
|
||||
tagsMenu.setFocusable(false);
|
||||
tagsMenu.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
|
||||
tagsMenu.setMaximumSize(new java.awt.Dimension(75, 21));
|
||||
tagsMenu.setMinimumSize(new java.awt.Dimension(75, 21));
|
||||
tagsMenu.setPreferredSize(new java.awt.Dimension(75, 21));
|
||||
tagsMenu.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
|
||||
tagsMenu.addMouseListener(new java.awt.event.MouseAdapter() {
|
||||
public void mousePressed(java.awt.event.MouseEvent evt) {
|
||||
tagsMenuMousePressed(evt);
|
||||
}
|
||||
});
|
||||
toolbar.add(tagsMenu);
|
||||
|
||||
add(toolbar);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
@ -450,12 +724,237 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan
|
||||
updateView();
|
||||
}//GEN-LAST:event_formComponentResized
|
||||
|
||||
/**
|
||||
* Deletes the selected tag when the Delete button is pressed in the Tag
|
||||
* Menu.
|
||||
*/
|
||||
private void deleteTag() {
|
||||
Platform.runLater(() -> {
|
||||
ImageTag tagInFocus = tagsGroup.getFocus();
|
||||
if (tagInFocus == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
ContentViewerTag<ImageTagRegion> contentViewerTag = tagInFocus.getContentViewerTag();
|
||||
scrollPane.setCursor(Cursor.WAIT);
|
||||
ContentViewerTagManager.deleteTag(contentViewerTag);
|
||||
Case.getCurrentCase().getServices().getTagsManager().deleteContentTag(contentViewerTag.getContentTag());
|
||||
tagsGroup.getChildren().remove(tagInFocus);
|
||||
} catch (TskCoreException | NoCurrentCaseException ex) {
|
||||
LOGGER.log(Level.WARNING, "Could not delete image tag in case db", ex); //NON-NLS
|
||||
}
|
||||
|
||||
scrollPane.setCursor(Cursor.DEFAULT);
|
||||
});
|
||||
|
||||
pcs.firePropertyChange(new PropertyChangeEvent(this,
|
||||
"state", null, State.CREATE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables create tag logic when the Create button is pressed in the Tags
|
||||
* Menu.
|
||||
*/
|
||||
private void createTag() {
|
||||
pcs.firePropertyChange(new PropertyChangeEvent(this,
|
||||
"state", null, State.DISABLE));
|
||||
imageTagCreator = new ImageTagCreator(fxImageView);
|
||||
|
||||
PropertyChangeListener newTagListener = (event) -> {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
ImageTagRegion tag = (ImageTagRegion) event.getNewValue();
|
||||
//Ask the user for tag name and comment
|
||||
TagNameAndComment result = GetTagNameAndCommentDialog.doDialog();
|
||||
if (result != null) {
|
||||
//Persist and build image tag
|
||||
Platform.runLater(() -> {
|
||||
try {
|
||||
scrollPane.setCursor(Cursor.WAIT);
|
||||
ContentViewerTag<ImageTagRegion> contentViewerTag = storeImageTag(tag, result);
|
||||
ImageTag imageTag = buildImageTag(contentViewerTag);
|
||||
tagsGroup.getChildren().add(imageTag);
|
||||
} catch (TskCoreException | SerializationException | NoCurrentCaseException ex) {
|
||||
LOGGER.log(Level.WARNING, "Could not save new image tag in case db", ex); //NON-NLS
|
||||
}
|
||||
|
||||
scrollPane.setCursor(Cursor.DEFAULT);
|
||||
});
|
||||
}
|
||||
|
||||
pcs.firePropertyChange(new PropertyChangeEvent(this,
|
||||
"state", null, State.CREATE));
|
||||
});
|
||||
|
||||
//Remove image tag creator from panel
|
||||
Platform.runLater(() -> {
|
||||
imageTagCreator.disconnect();
|
||||
masterGroup.getChildren().remove(imageTagCreator);
|
||||
});
|
||||
};
|
||||
|
||||
imageTagCreator.addNewTagListener(newTagListener);
|
||||
Platform.runLater(() -> masterGroup.getChildren().add(imageTagCreator));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an ImageTag instance from the ContentViewerTag.
|
||||
*
|
||||
* @param contentViewerTag
|
||||
* @return
|
||||
*/
|
||||
private ImageTag buildImageTag(ContentViewerTag<ImageTagRegion> contentViewerTag) {
|
||||
ImageTag imageTag = new ImageTag(contentViewerTag, fxImageView);
|
||||
|
||||
//Automatically persist edits made by user
|
||||
imageTag.subscribeToEditEvents((edit) -> {
|
||||
try {
|
||||
scrollPane.setCursor(Cursor.WAIT);
|
||||
ImageTagRegion newRegion = (ImageTagRegion) edit.getNewValue();
|
||||
ContentViewerTagManager.updateTag(contentViewerTag, newRegion);
|
||||
} catch (SerializationException | TskCoreException | NoCurrentCaseException ex) {
|
||||
LOGGER.log(Level.WARNING, "Could not save edit for image tag in case db", ex); //NON-NLS
|
||||
}
|
||||
scrollPane.setCursor(Cursor.DEFAULT);
|
||||
});
|
||||
return imageTag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the image tag by creating a ContentTag instance and associating
|
||||
* the ImageTagRegion data with it in the case database.
|
||||
*
|
||||
* @param data
|
||||
* @param result
|
||||
*/
|
||||
private ContentViewerTag<ImageTagRegion> storeImageTag(ImageTagRegion data, TagNameAndComment result)
|
||||
throws TskCoreException, SerializationException, NoCurrentCaseException {
|
||||
scrollPane.setCursor(Cursor.WAIT);
|
||||
try {
|
||||
ContentTag contentTag = Case.getCurrentCaseThrows().getServices().getTagsManager()
|
||||
.addContentTag(file, result.getTagName(), result.getComment());
|
||||
return ContentViewerTagManager.saveTag(contentTag, data);
|
||||
} finally {
|
||||
scrollPane.setCursor(Cursor.DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides or show tags when the Hide or Show button is pressed in the Tags
|
||||
* Menu.
|
||||
*/
|
||||
private void showOrHideTags() {
|
||||
Platform.runLater(() -> {
|
||||
if (DisplayOptions.HIDE_TAGS.getName().equals(hideTagsMenuItem.getText())) {
|
||||
//Temporarily remove the tags group and update buttons
|
||||
masterGroup.getChildren().remove(tagsGroup);
|
||||
hideTagsMenuItem.setText(DisplayOptions.SHOW_TAGS.getName());
|
||||
tagsGroup.clearFocus();
|
||||
pcs.firePropertyChange(new PropertyChangeEvent(this,
|
||||
"state", null, State.HIDDEN));
|
||||
} else {
|
||||
//Add tags group back in and update buttons
|
||||
masterGroup.getChildren().add(tagsGroup);
|
||||
hideTagsMenuItem.setText(DisplayOptions.HIDE_TAGS.getName());
|
||||
pcs.firePropertyChange(new PropertyChangeEvent(this,
|
||||
"state", null, State.VISIBLE));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NbBundle.Messages({
|
||||
"MediaViewImagePanel.exportSaveText=Save",
|
||||
"MediaViewImagePanel.successfulExport=Tagged image was successfully saved.",
|
||||
"MediaViewImagePanel.unsuccessfulExport=Unable to export tagged image to disk.",
|
||||
"MediaViewImagePanel.fileChooserTitle=Choose a save location"
|
||||
})
|
||||
private void exportTags() {
|
||||
tagsGroup.clearFocus();
|
||||
exportChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
||||
//Always base chooser location to export folder
|
||||
exportChooser.setCurrentDirectory(new File(Case.getCurrentCase().getExportDirectory()));
|
||||
int returnVal = exportChooser.showDialog(this, Bundle.MediaViewImagePanel_exportSaveText());
|
||||
if (returnVal == JFileChooser.APPROVE_OPTION) {
|
||||
new SwingWorker<Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground() {
|
||||
try {
|
||||
//Retrieve content viewer tags
|
||||
List<ContentTag> tags = Case.getCurrentCase().getServices()
|
||||
.getTagsManager().getContentTagsByContent(file);
|
||||
List<ContentViewerTag<ImageTagRegion>> contentViewerTags = getContentViewerTags(tags);
|
||||
|
||||
//Pull out image tag regions
|
||||
Collection<ImageTagRegion> regions = contentViewerTags.stream()
|
||||
.map(cvTag -> cvTag.getDetails()).collect(Collectors.toList());
|
||||
|
||||
//Apply tags to image and write to file
|
||||
BufferedImage taggedImage = ImageTagsUtil.getImageWithTags(file, regions);
|
||||
Path output = Paths.get(exportChooser.getSelectedFile().getPath(),
|
||||
FilenameUtils.getBaseName(file.getName()) + "-with_tags.png"); //NON-NLS
|
||||
ImageIO.write(taggedImage, "png", output.toFile());
|
||||
|
||||
JOptionPane.showMessageDialog(null, Bundle.MediaViewImagePanel_successfulExport());
|
||||
} catch (Exception ex) { //Runtime exceptions may spill out of ImageTagsUtil from JavaFX.
|
||||
//This ensures we (devs and users) have something when it doesn't work.
|
||||
LOGGER.log(Level.WARNING, "Unable to export tagged image to disk", ex); //NON-NLS
|
||||
JOptionPane.showMessageDialog(null, Bundle.MediaViewImagePanel_unsuccessfulExport());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
}
|
||||
|
||||
private void tagsMenuMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_tagsMenuMousePressed
|
||||
if (imageTaggingOptions.isEnabled()) {
|
||||
imageTaggingOptions.show(tagsMenu, -300 + tagsMenu.getWidth(), tagsMenu.getHeight() + 3);
|
||||
}
|
||||
}//GEN-LAST:event_tagsMenuMousePressed
|
||||
|
||||
/**
|
||||
* Display states for the show/hide tags button.
|
||||
*/
|
||||
enum DisplayOptions {
|
||||
HIDE_TAGS("Hide"),
|
||||
SHOW_TAGS("Show");
|
||||
|
||||
private final String name;
|
||||
|
||||
DisplayOptions(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Different states that the content viewer can be in. These states drive
|
||||
* which buttons are enabled for tagging.
|
||||
*/
|
||||
enum State {
|
||||
HIDDEN,
|
||||
VISIBLE,
|
||||
SELECTED,
|
||||
CREATE,
|
||||
EMPTY,
|
||||
NONEMPTY,
|
||||
DEFAULT,
|
||||
DISABLE;
|
||||
}
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.Box.Filler filler1;
|
||||
private javax.swing.Box.Filler filler2;
|
||||
private javax.swing.JPanel jPanel1;
|
||||
private javax.swing.JToolBar.Separator jSeparator1;
|
||||
private javax.swing.JToolBar.Separator jSeparator2;
|
||||
private javax.swing.JButton rotateLeftButton;
|
||||
private javax.swing.JButton rotateRightButton;
|
||||
private javax.swing.JTextField rotationTextField;
|
||||
private javax.swing.JButton tagsMenu;
|
||||
private javax.swing.JToolBar toolbar;
|
||||
private javax.swing.JButton zoomInButton;
|
||||
private javax.swing.JButton zoomOutButton;
|
||||
@ -601,8 +1100,8 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan
|
||||
// Add the transforms in reverse order of intended execution.
|
||||
// Note: They MUST be added in this order to ensure translate is
|
||||
// executed last.
|
||||
imageGroup.getTransforms().clear();
|
||||
imageGroup.getTransforms().addAll(translate, rotate, scale);
|
||||
masterGroup.getTransforms().clear();
|
||||
masterGroup.getTransforms().addAll(translate, rotate, scale);
|
||||
|
||||
// Adjust scroll bar positions for view changes.
|
||||
if (viewportWidth > fxPanel.getWidth()) {
|
||||
@ -618,107 +1117,4 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan
|
||||
rotationTextField.setText((int) rotation + "°");
|
||||
zoomTextField.setText((Math.round(zoomRatio * 100.0)) + "%");
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables users to 'tag' a region of an image by clicking and dragging a
|
||||
* rectangle overtop.
|
||||
*/
|
||||
class ImageTaggingTool extends Rectangle {
|
||||
|
||||
private final double imageWidth;
|
||||
private final double imageHeight;
|
||||
private final double imageOriginX;
|
||||
private final double imageOriginY;
|
||||
|
||||
//Origin of the drag event.
|
||||
private double rectangleOriginX;
|
||||
private double rectangleOriginY;
|
||||
|
||||
//Rectangle lines should be 1.5% of the image. This level of thickness has
|
||||
//a good balance between visual acuity and loss of selection at the borders
|
||||
//of the image.
|
||||
private double lineThicknessAsPercent = 1.5;
|
||||
|
||||
/**
|
||||
* Adds tagging support to an image, where the 'tag' rectangle will be
|
||||
* the specified color.
|
||||
*
|
||||
* @param image Image to tag
|
||||
* @param color Color of the 'tag' rectangle
|
||||
*/
|
||||
private ImageTaggingTool(ImageView image, Color color) {
|
||||
defaultSettings();
|
||||
|
||||
imageWidth = image.getImage().getWidth();
|
||||
imageHeight = image.getImage().getHeight();
|
||||
imageOriginX = image.getX();
|
||||
imageOriginY = image.getY();
|
||||
|
||||
setStroke(color);
|
||||
setFill(color.deriveColor(0, 0, 0, 0));
|
||||
|
||||
//Calculate how many pixels the stroke width should be to guarentee
|
||||
//a consistent % of image consumed by the rectangle border.
|
||||
double min = Math.min(imageWidth, imageHeight);
|
||||
double lineThicknessPixels = min * lineThicknessAsPercent / 100.0;
|
||||
setStrokeWidth(lineThicknessPixels);
|
||||
setVisible(false);
|
||||
|
||||
//Create a rectangle by left clicking on the image
|
||||
image.setOnMousePressed((MouseEvent event) -> {
|
||||
if (event.isSecondaryButtonDown()) {
|
||||
return;
|
||||
}
|
||||
|
||||
//Reset box on new click.
|
||||
defaultSettings();
|
||||
|
||||
rectangleOriginX = event.getX();
|
||||
rectangleOriginY = event.getY();
|
||||
|
||||
setX(rectangleOriginX);
|
||||
setY(rectangleOriginY);
|
||||
});
|
||||
|
||||
//Adjust the rectangle by dragging the left mouse button
|
||||
image.setOnMouseDragged((MouseEvent event) -> {
|
||||
if (event.isSecondaryButtonDown()) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the rectangle is contained within image boundaries and
|
||||
* that the line thickness is kept within bounds.
|
||||
*/
|
||||
double newX = Math.min(Math.max(event.getX(), imageOriginX)
|
||||
+ lineThicknessPixels / 2, imageWidth - lineThicknessPixels / 2);
|
||||
double newY = Math.min(Math.max(event.getY(), imageOriginY)
|
||||
+ lineThicknessPixels / 2, imageHeight - lineThicknessPixels / 2);
|
||||
|
||||
setVisible(true);
|
||||
double offsetX = newX - rectangleOriginX;
|
||||
if (offsetX < 0) {
|
||||
setX(newX);
|
||||
}
|
||||
setWidth(Math.abs(offsetX));
|
||||
|
||||
double offsetY = newY - rectangleOriginY;
|
||||
if (offsetY < 0) {
|
||||
setY(newY);
|
||||
}
|
||||
setHeight(Math.abs(offsetY));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the rectangle to default dimensions.
|
||||
*/
|
||||
public final void defaultSettings() {
|
||||
setX(0);
|
||||
setY(0);
|
||||
setWidth(0);
|
||||
setHeight(0);
|
||||
setVisible(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -271,22 +271,7 @@
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="htmlPanel" alignment="0" pref="647" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="htmlPanel" alignment="0" pref="362" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="org.sleuthkit.autopsy.contentviewers.HtmlPanel" name="htmlPanel">
|
||||
</Component>
|
||||
</SubComponents>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
|
||||
</Container>
|
||||
<Container class="javax.swing.JScrollPane" name="rtfbodyScrollPane">
|
||||
<Properties>
|
||||
|
@ -87,7 +87,7 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
|
||||
private static final int ATTM_TAB_INDEX = 4;
|
||||
|
||||
private final List<JTextComponent> textAreas;
|
||||
|
||||
private final org.sleuthkit.autopsy.contentviewers.HtmlPanel htmlPanel = new org.sleuthkit.autopsy.contentviewers.HtmlPanel();
|
||||
/**
|
||||
* Artifact currently being displayed
|
||||
*/
|
||||
@ -101,6 +101,7 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
|
||||
@NbBundle.Messages("MessageContentViewer.AtrachmentsPanel.title=Attachments")
|
||||
public MessageContentViewer() {
|
||||
initComponents();
|
||||
htmlPane.add(htmlPanel);
|
||||
envelopePanel.setBackground(new Color(0, 0, 0, 38));
|
||||
drp = DataResultPanel.createInstanceUninitialized(Bundle.MessageContentViewer_AtrachmentsPanel_title(), "", new TableFilterNode(Node.EMPTY, false), 0, null);
|
||||
attachmentsScrollPane.setViewportView(drp);
|
||||
@ -153,7 +154,6 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
|
||||
textbodyScrollPane = new javax.swing.JScrollPane();
|
||||
textbodyTextArea = new javax.swing.JTextArea();
|
||||
htmlPane = new javax.swing.JPanel();
|
||||
htmlPanel = new org.sleuthkit.autopsy.contentviewers.HtmlPanel();
|
||||
rtfbodyScrollPane = new javax.swing.JScrollPane();
|
||||
rtfbodyTextPane = new javax.swing.JTextPane();
|
||||
attachmentsPanel = new javax.swing.JPanel();
|
||||
@ -266,17 +266,7 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
|
||||
|
||||
msgbodyTabbedPane.addTab(org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.textbodyScrollPane.TabConstraints.tabTitle"), textbodyScrollPane); // NOI18N
|
||||
|
||||
javax.swing.GroupLayout htmlPaneLayout = new javax.swing.GroupLayout(htmlPane);
|
||||
htmlPane.setLayout(htmlPaneLayout);
|
||||
htmlPaneLayout.setHorizontalGroup(
|
||||
htmlPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(htmlPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 647, Short.MAX_VALUE)
|
||||
);
|
||||
htmlPaneLayout.setVerticalGroup(
|
||||
htmlPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(htmlPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 362, Short.MAX_VALUE)
|
||||
);
|
||||
|
||||
htmlPane.setLayout(new java.awt.BorderLayout());
|
||||
msgbodyTabbedPane.addTab(org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.htmlPane.TabConstraints.tabTitle"), htmlPane); // NOI18N
|
||||
|
||||
rtfbodyScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
|
||||
@ -357,7 +347,6 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
|
||||
private javax.swing.JScrollPane headersScrollPane;
|
||||
private javax.swing.JTextArea headersTextArea;
|
||||
private javax.swing.JPanel htmlPane;
|
||||
private org.sleuthkit.autopsy.contentviewers.HtmlPanel htmlPanel;
|
||||
private javax.swing.JTabbedPane msgbodyTabbedPane;
|
||||
private javax.swing.JScrollPane rtfbodyScrollPane;
|
||||
private javax.swing.JTextPane rtfbodyTextPane;
|
||||
@ -534,7 +523,7 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
|
||||
textComponent.setCaretPosition(0); //make sure we start at the top
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final boolean hasText = attributeText.length() > 0;
|
||||
|
||||
msgbodyTabbedPane.setEnabledAt(index, hasText);
|
||||
@ -680,18 +669,18 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
|
||||
protected Sheet createSheet() {
|
||||
Sheet sheet = super.createSheet();
|
||||
Set<String> keepProps = new HashSet<>(Arrays.asList(
|
||||
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.nameColLbl"),
|
||||
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.score.name"),
|
||||
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.comment.name"),
|
||||
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.count.name"),
|
||||
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.sizeColLbl"),
|
||||
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.mimeType"),
|
||||
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.knownColLbl")));
|
||||
|
||||
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.nameColLbl"),
|
||||
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.score.name"),
|
||||
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.comment.name"),
|
||||
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.count.name"),
|
||||
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.sizeColLbl"),
|
||||
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.mimeType"),
|
||||
NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.knownColLbl")));
|
||||
|
||||
//Remove all other props except for the ones above
|
||||
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
|
||||
for(Property<?> p : sheetSet.getProperties()) {
|
||||
if(!keepProps.contains(p.getName())){
|
||||
for (Property<?> p : sheetSet.getProperties()) {
|
||||
if (!keepProps.contains(p.getName())) {
|
||||
sheetSet.remove(p.getName());
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,353 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> 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.contentviewers.imagetagging;
|
||||
|
||||
import com.sun.javafx.event.EventDispatchChainImpl;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
import javafx.collections.ListChangeListener;
|
||||
import javafx.scene.Cursor;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.Tooltip;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.shape.Circle;
|
||||
import javafx.scene.shape.Rectangle;
|
||||
import org.sleuthkit.autopsy.casemodule.services.contentviewertags.ContentViewerTagManager.ContentViewerTag;
|
||||
|
||||
/**
|
||||
* A tagged region displayed over an image. This class contains a "physical tag"
|
||||
* and 8 edit "handles". The physical tag is a plain old rectangle that defines
|
||||
* the tag boundaries. The edit handles serve two purposes. One is to represent
|
||||
* selection. All 8 edit handles will become visible overtop the physical tag
|
||||
* when the user clicks on the rectangle. The other purpose is to allow the user to edit
|
||||
* and manipulate the physical tag boundaries (hence the name, edit handle).
|
||||
* This class should be treated as a logical image tag.
|
||||
*/
|
||||
public final class ImageTag extends Group {
|
||||
|
||||
// Used to tell the 8 edit handles to hide if this tag is no longer selected
|
||||
private final EventDispatchChainImpl ALL_CHILDREN;
|
||||
|
||||
private final PhysicalTag physicalTag;
|
||||
|
||||
//Notifies listeners that the user has editted the tag boundaries
|
||||
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
|
||||
|
||||
//The underlying presistent tag details that this image tag originates from
|
||||
private final ContentViewerTag<ImageTagRegion> appTag;
|
||||
|
||||
public ImageTag(ContentViewerTag<ImageTagRegion> contentViewerTag, ImageView image) {
|
||||
ALL_CHILDREN = new EventDispatchChainImpl();
|
||||
this.appTag = contentViewerTag;
|
||||
|
||||
this.getChildren().addListener((ListChangeListener<Node>) change -> {
|
||||
change.next();
|
||||
change.getAddedSubList().forEach((node) -> ALL_CHILDREN.append(node.getEventDispatcher()));
|
||||
});
|
||||
|
||||
ImageTagRegion details = contentViewerTag.getDetails();
|
||||
physicalTag = new PhysicalTag(details);
|
||||
|
||||
//Defines the max allowable boundary that a user may drag any given handle.
|
||||
Boundary dragBoundary = (x, y) -> {
|
||||
double boundingX = image.getX();
|
||||
double boundingY = image.getY();
|
||||
double width = image.getImage().getWidth();
|
||||
double height = image.getImage().getHeight();
|
||||
|
||||
return x > boundingX + details.getStrokeThickness() / 2
|
||||
&& x < boundingX + width - details.getStrokeThickness() / 2
|
||||
&& y > boundingY + details.getStrokeThickness() / 2
|
||||
&& y < boundingY + height - details.getStrokeThickness() / 2;
|
||||
};
|
||||
|
||||
EditHandle bottomLeft = new EditHandle(physicalTag)
|
||||
.setPosition(Position.bottom(), Position.left())
|
||||
.setDrag(dragBoundary, Draggable.bottom(), Draggable.left());
|
||||
|
||||
EditHandle bottomRight = new EditHandle(physicalTag)
|
||||
.setPosition(Position.bottom(), Position.right())
|
||||
.setDrag(dragBoundary, Draggable.bottom(), Draggable.right());
|
||||
|
||||
EditHandle topLeft = new EditHandle(physicalTag)
|
||||
.setPosition(Position.top(), Position.left())
|
||||
.setDrag(dragBoundary, Draggable.top(), Draggable.left());
|
||||
|
||||
EditHandle topRight = new EditHandle(physicalTag)
|
||||
.setPosition(Position.top(), Position.right())
|
||||
.setDrag(dragBoundary, Draggable.top(), Draggable.right());
|
||||
|
||||
EditHandle bottomMiddle = new EditHandle(physicalTag)
|
||||
.setPosition(Position.bottom(), Position.xMiddle())
|
||||
.setDrag(dragBoundary, Draggable.bottom());
|
||||
|
||||
EditHandle topMiddle = new EditHandle(physicalTag)
|
||||
.setPosition(Position.top(), Position.xMiddle())
|
||||
.setDrag(dragBoundary, Draggable.top());
|
||||
|
||||
EditHandle rightMiddle = new EditHandle(physicalTag)
|
||||
.setPosition(Position.right(), Position.yMiddle())
|
||||
.setDrag(dragBoundary, Draggable.right());
|
||||
|
||||
EditHandle leftMiddle = new EditHandle(physicalTag)
|
||||
.setPosition(Position.left(), Position.yMiddle())
|
||||
.setDrag(dragBoundary, Draggable.left());
|
||||
|
||||
//The "logical" tag is the Group
|
||||
this.getChildren().addAll(physicalTag, bottomLeft, bottomRight, topLeft,
|
||||
topRight, bottomMiddle, topMiddle, rightMiddle, leftMiddle);
|
||||
|
||||
Tooltip.install(this, new Tooltip(contentViewerTag.getContentTag()
|
||||
.getName().getDisplayName()));
|
||||
|
||||
this.addEventHandler(ImageTagControls.NOT_FOCUSED, event -> ALL_CHILDREN.dispatchEvent(event));
|
||||
this.addEventHandler(ImageTagControls.FOCUSED, event -> ALL_CHILDREN.dispatchEvent(event));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new listener for edit events. These events are generated when a
|
||||
* user drags on one of the edit "knobs" of the tag.
|
||||
*
|
||||
* @param listener
|
||||
*/
|
||||
public void subscribeToEditEvents(PropertyChangeListener listener) {
|
||||
pcs.addPropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
public double getWidth() {
|
||||
return physicalTag.getWidth();
|
||||
}
|
||||
|
||||
public double getHeight() {
|
||||
return physicalTag.getHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the content viewer tag that this class represents.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public ContentViewerTag<ImageTagRegion> getContentViewerTag() {
|
||||
return appTag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Plain old rectangle that represents an unselected Image Tag
|
||||
*/
|
||||
class PhysicalTag extends Rectangle {
|
||||
|
||||
public PhysicalTag(ImageTagRegion details) {
|
||||
this.setStroke(Color.RED);
|
||||
this.setFill(Color.RED.deriveColor(0, 0, 0, 0));
|
||||
this.setStrokeWidth(details.getStrokeThickness());
|
||||
|
||||
setX(details.getX());
|
||||
setY(details.getY());
|
||||
setWidth(details.getWidth());
|
||||
setHeight(details.getHeight());
|
||||
|
||||
this.addEventHandler(ImageTagControls.NOT_FOCUSED, event -> this.setOpacity(1));
|
||||
this.addEventHandler(ImageTagControls.FOCUSED, event -> this.setOpacity(0.5));
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a portable description of the tag region.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public ImageTagRegion getState() {
|
||||
return new ImageTagRegion()
|
||||
.setX(this.getX())
|
||||
.setY(this.getY())
|
||||
.setWidth(this.getWidth())
|
||||
.setHeight(this.getHeight())
|
||||
.setStrokeThickness(this.getStrokeWidth());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draggable "knob" used to manipulate the physical tag boundaries.
|
||||
*/
|
||||
class EditHandle extends Circle {
|
||||
|
||||
private final PhysicalTag parent;
|
||||
|
||||
public EditHandle(PhysicalTag parent) {
|
||||
this.setVisible(false);
|
||||
|
||||
//Hide when the tag is not selected.
|
||||
this.addEventHandler(ImageTagControls.NOT_FOCUSED, event -> this.setVisible(false));
|
||||
this.addEventHandler(ImageTagControls.FOCUSED, event -> this.setVisible(true));
|
||||
|
||||
this.setRadius(parent.getStrokeWidth());
|
||||
this.setFill(parent.getStroke());
|
||||
|
||||
this.setOnDragDetected(event -> {
|
||||
this.getParent().setCursor(Cursor.CLOSED_HAND);
|
||||
});
|
||||
|
||||
this.setOnMouseReleased(event -> {
|
||||
this.getParent().setCursor(Cursor.DEFAULT);
|
||||
pcs.firePropertyChange(new PropertyChangeEvent(this, "Tag Edit", null, parent.getState()));
|
||||
});
|
||||
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the positioning of this edit handle on the physical tag.
|
||||
*
|
||||
* @param vals
|
||||
* @return
|
||||
*/
|
||||
public EditHandle setPosition(Position... vals) {
|
||||
for (Position pos : vals) {
|
||||
parent.widthProperty().addListener((obs, oldVal, newVal) -> pos.set(parent, this));
|
||||
parent.heightProperty().addListener((obs, oldVal, newVal) -> pos.set(parent, this));
|
||||
pos.set(parent, this);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the drag capabilities for manipulating the physical tag.
|
||||
*
|
||||
* @param bounds
|
||||
* @param vals
|
||||
* @return
|
||||
*/
|
||||
public EditHandle setDrag(Boundary bounds, Draggable... vals) {
|
||||
this.setOnMouseDragged((event) -> {
|
||||
for (Draggable drag : vals) {
|
||||
drag.perform(parent, event, bounds);
|
||||
}
|
||||
});
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Position strategies for "sticking" to a location on the physical tag when
|
||||
* it is resized.
|
||||
*/
|
||||
static interface Position {
|
||||
|
||||
void set(PhysicalTag parent, Circle knob);
|
||||
|
||||
static Position left() {
|
||||
return (parent, knob) -> knob.centerXProperty().bind(parent.xProperty());
|
||||
}
|
||||
|
||||
static Position right() {
|
||||
return (parent, knob) -> knob.centerXProperty().bind(parent.xProperty().add(parent.getWidth()));
|
||||
}
|
||||
|
||||
static Position top() {
|
||||
return (parent, knob) -> knob.centerYProperty().bind(parent.yProperty());
|
||||
}
|
||||
|
||||
static Position bottom() {
|
||||
return (parent, knob) -> knob.centerYProperty().bind(parent.yProperty().add(parent.getHeight()));
|
||||
}
|
||||
|
||||
static Position xMiddle() {
|
||||
return (parent, knob) -> knob.centerXProperty().bind(parent.xProperty().add(parent.getWidth() / 2));
|
||||
}
|
||||
|
||||
static Position yMiddle() {
|
||||
return (parent, knob) -> knob.centerYProperty().bind(parent.yProperty().add(parent.getHeight() / 2));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the bounding box for which dragging is allowable.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
static interface Boundary {
|
||||
|
||||
boolean isPointInBounds(double x, double y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drag strategies for manipulating the physical tag from a given side of
|
||||
* the rectangle.
|
||||
*/
|
||||
static interface Draggable {
|
||||
|
||||
void perform(PhysicalTag parent, MouseEvent event, Boundary b);
|
||||
|
||||
static Draggable bottom() {
|
||||
return (parent, event, bounds) -> {
|
||||
if (!bounds.isPointInBounds(event.getX(), event.getY())) {
|
||||
return;
|
||||
}
|
||||
|
||||
double deltaY = event.getY() - parent.getY();
|
||||
if (deltaY > 0) {
|
||||
parent.setHeight(deltaY);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static Draggable top() {
|
||||
return (parent, event, bounds) -> {
|
||||
if (!bounds.isPointInBounds(event.getX(), event.getY())) {
|
||||
return;
|
||||
}
|
||||
|
||||
double deltaY = parent.getY() + parent.getHeight() - event.getY();
|
||||
if (deltaY < parent.getY() + parent.getHeight() && deltaY > 0) {
|
||||
parent.setHeight(deltaY);
|
||||
parent.setY(event.getY());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static Draggable left() {
|
||||
return (parent, event, bounds) -> {
|
||||
if (!bounds.isPointInBounds(event.getX(), event.getY())) {
|
||||
return;
|
||||
}
|
||||
|
||||
double deltaX = parent.getX() + parent.getWidth() - event.getX();
|
||||
if (deltaX < parent.getX() + parent.getWidth() && deltaX > 0) {
|
||||
parent.setWidth(deltaX);
|
||||
parent.setX(event.getX());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static Draggable right() {
|
||||
return (parent, event, bounds) -> {
|
||||
if (!bounds.isPointInBounds(event.getX(), event.getY())) {
|
||||
return;
|
||||
}
|
||||
|
||||
double deltaX = event.getX() - parent.getX();
|
||||
if (deltaX > 0) {
|
||||
parent.setWidth(deltaX);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> 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.contentviewers.imagetagging;
|
||||
|
||||
import javafx.event.Event;
|
||||
import javafx.event.EventType;
|
||||
|
||||
/**
|
||||
* Focus events for ImageTags to consume. These events trigger selection behavior
|
||||
* on ImageTags and are originated from the ImageTagsGroup class.
|
||||
*/
|
||||
public class ImageTagControls {
|
||||
public static final EventType<Event> NOT_FOCUSED = new EventType<>("NOT_FOCUSED");
|
||||
public static final EventType<Event> FOCUSED = new EventType<>("FOCUSED");
|
||||
}
|
@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> 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.contentviewers.imagetagging;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.shape.Rectangle;
|
||||
|
||||
/**
|
||||
* Creates image tags. This class attaches itself to a source image, waiting
|
||||
* for mouse press, mouse drag, and mouse release events. Upon a mouse release
|
||||
* event, any listeners are updated with the portable description of the new tag
|
||||
* boundaries (ImageTagRegion).
|
||||
*/
|
||||
public final class ImageTagCreator extends Rectangle {
|
||||
|
||||
//Origin of the drag event.
|
||||
private double rectangleOriginX, rectangleOriginY;
|
||||
|
||||
//Rectangle lines should be 1.5% of the image. This level of thickness has
|
||||
//a good balance between visual acuity and loss of selection at the borders
|
||||
//of the image.
|
||||
private final static double LINE_THICKNESS_PERCENT = 1.5;
|
||||
private final double minArea;
|
||||
|
||||
//Used to update listeners of the new tag boundaries
|
||||
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
|
||||
|
||||
private final EventHandler<MouseEvent> mousePressed;
|
||||
private final EventHandler<MouseEvent> mouseDragged;
|
||||
private final EventHandler<MouseEvent> mouseReleased;
|
||||
|
||||
//Handles the unregistering this ImageTagCreator from mouse press, mouse drag,
|
||||
//and mouse release events of the source image.
|
||||
private final Runnable disconnectRunnable;
|
||||
|
||||
/**
|
||||
* Adds tagging support to an image, where the 'tag' rectangle will be the
|
||||
* specified color.
|
||||
*
|
||||
* @param image Image to tag
|
||||
*/
|
||||
public ImageTagCreator(ImageView image) {
|
||||
setStroke(Color.RED);
|
||||
setFill(Color.RED.deriveColor(0, 0, 0, 0));
|
||||
|
||||
//Calculate how many pixels the stroke width should be to guarentee
|
||||
//a consistent % of image consumed by the rectangle border.
|
||||
double min = Math.min(image.getImage().getWidth(), image.getImage().getHeight());
|
||||
double lineThicknessPixels = min * LINE_THICKNESS_PERCENT / 100.0;
|
||||
setStrokeWidth(lineThicknessPixels);
|
||||
minArea = lineThicknessPixels * lineThicknessPixels;
|
||||
setVisible(false);
|
||||
|
||||
this.mousePressed = (MouseEvent event) -> {
|
||||
if (event.isSecondaryButtonDown()) {
|
||||
return;
|
||||
}
|
||||
|
||||
//Reset box on new click.
|
||||
defaultSettings();
|
||||
rectangleOriginX = event.getX();
|
||||
rectangleOriginY = event.getY();
|
||||
|
||||
setX(rectangleOriginX);
|
||||
setY(rectangleOriginY);
|
||||
};
|
||||
|
||||
image.addEventHandler(MouseEvent.MOUSE_PRESSED, this.mousePressed);
|
||||
|
||||
this.mouseDragged = (MouseEvent event) -> {
|
||||
if (event.isSecondaryButtonDown()) {
|
||||
return;
|
||||
}
|
||||
|
||||
double currentX = event.getX(), currentY = event.getY();
|
||||
|
||||
/**
|
||||
* Ensure the rectangle is contained within image boundaries and
|
||||
* that the line thickness is kept within bounds.
|
||||
*/
|
||||
double newX = Math.min(Math.max(currentX, image.getX())
|
||||
+ lineThicknessPixels / 2, image.getImage().getWidth() - lineThicknessPixels / 2);
|
||||
double newY = Math.min(Math.max(currentY, image.getY())
|
||||
+ lineThicknessPixels / 2, image.getImage().getHeight() - lineThicknessPixels / 2);
|
||||
|
||||
setVisible(true);
|
||||
double offsetX = newX - rectangleOriginX;
|
||||
if (offsetX < 0) {
|
||||
setX(newX);
|
||||
}
|
||||
setWidth(Math.abs(offsetX));
|
||||
|
||||
double offsetY = newY - rectangleOriginY;
|
||||
if (offsetY < 0) {
|
||||
setY(newY);
|
||||
}
|
||||
setHeight(Math.abs(offsetY));
|
||||
};
|
||||
|
||||
image.addEventHandler(MouseEvent.MOUSE_DRAGGED, this.mouseDragged);
|
||||
|
||||
this.mouseReleased = event -> {
|
||||
//Reject any drags that are too small to count as a meaningful tag.
|
||||
//Meaningful is described as having an area that is visible that is
|
||||
//not consumed by the thickness of the stroke.
|
||||
if ((this.getWidth() - this.getStrokeWidth())
|
||||
* (this.getHeight() - this.getStrokeWidth()) <= minArea) {
|
||||
defaultSettings();
|
||||
return;
|
||||
}
|
||||
|
||||
this.pcs.firePropertyChange(new PropertyChangeEvent(this, "New Tag",
|
||||
null, new ImageTagRegion()
|
||||
.setX(this.getX())
|
||||
.setY(this.getY())
|
||||
.setWidth(this.getWidth())
|
||||
.setHeight(this.getHeight())
|
||||
.setStrokeThickness(lineThicknessPixels)));
|
||||
};
|
||||
|
||||
image.addEventHandler(MouseEvent.MOUSE_RELEASED, this.mouseReleased);
|
||||
|
||||
//Used to remove itself from mouse events on the source image
|
||||
disconnectRunnable = () -> {
|
||||
defaultSettings();
|
||||
image.removeEventHandler(MouseEvent.MOUSE_RELEASED, mouseReleased);
|
||||
image.removeEventHandler(MouseEvent.MOUSE_DRAGGED, mouseDragged);
|
||||
image.removeEventHandler(MouseEvent.MOUSE_PRESSED, mousePressed);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a PCL for new tag events. Listeners are updated with a portable
|
||||
* description (ImageTagRegion) of the new tag, which represent the
|
||||
* rectangle boundaries.
|
||||
*
|
||||
* @param listener
|
||||
*/
|
||||
public void addNewTagListener(PropertyChangeListener listener) {
|
||||
this.pcs.addPropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes itself from mouse events on the source image.
|
||||
*/
|
||||
public void disconnect() {
|
||||
this.disconnectRunnable.run();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the rectangle to default dimensions.
|
||||
*/
|
||||
private void defaultSettings() {
|
||||
setWidth(0);
|
||||
setHeight(0);
|
||||
setVisible(false);
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> 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.contentviewers.imagetagging;
|
||||
|
||||
/**
|
||||
* Bean representation of an image tag. This class is used for storage and
|
||||
* retrieval of ImageTags from the case database.
|
||||
*/
|
||||
public class ImageTagRegion {
|
||||
|
||||
/**
|
||||
* These fields will be serialized and stored in the case database by the
|
||||
* ContentViewerTagManager.
|
||||
*/
|
||||
private double x;
|
||||
private double y;
|
||||
private double width;
|
||||
private double height;
|
||||
|
||||
private double strokeThickness;
|
||||
|
||||
public ImageTagRegion setStrokeThickness(double thickness) {
|
||||
this.strokeThickness = thickness;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ImageTagRegion setX(double x) {
|
||||
this.x = x;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ImageTagRegion setWidth(double width) {
|
||||
this.width = width;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ImageTagRegion setY(double y) {
|
||||
this.y = y;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ImageTagRegion setHeight(double height) {
|
||||
this.height = height;
|
||||
return this;
|
||||
}
|
||||
|
||||
public double getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public double getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public double getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public double getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public double getStrokeThickness() {
|
||||
return strokeThickness;
|
||||
}
|
||||
}
|
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> 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.contentviewers.imagetagging;
|
||||
|
||||
import com.sun.javafx.event.EventDispatchChainImpl;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
import javafx.event.Event;
|
||||
import javafx.geometry.Point2D;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
|
||||
/**
|
||||
* Manages the focus and z-ordering of ImageTags. Only one image tag may be
|
||||
* selected at a time. Image tags show their 8 edit "handles" upon selection
|
||||
* (see ImageTag class for more details) and get the highest z-ordering to make
|
||||
* editing easier. This class is responsible for setting and dropping focus as
|
||||
* the user navigates from tag to tag. The ImageTag is treated as a logical
|
||||
* unit, however it's underlying representation consists of the physical
|
||||
* rectangle and the 8 edit handles. JavaFX will report selection on the Node
|
||||
* level (so either the Rectangle, or a singe edit handle), which makes keeping
|
||||
* the entire image tag in focus a non-trivial problem.
|
||||
*/
|
||||
public final class ImageTagsGroup extends Group {
|
||||
|
||||
private final EventDispatchChainImpl NO_OP_CHAIN = new EventDispatchChainImpl();
|
||||
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
|
||||
|
||||
private volatile ImageTag currentFocus;
|
||||
|
||||
public ImageTagsGroup(Node backDrop) {
|
||||
|
||||
//Reset focus of current selection if the back drop has focus.
|
||||
backDrop.setOnMousePressed((mouseEvent) -> {
|
||||
if (currentFocus != null) {
|
||||
currentFocus.getEventDispatcher().dispatchEvent(
|
||||
new Event(ImageTagControls.NOT_FOCUSED), NO_OP_CHAIN);
|
||||
}
|
||||
|
||||
this.pcs.firePropertyChange(new PropertyChangeEvent(this,
|
||||
ImageTagControls.NOT_FOCUSED.getName(), currentFocus, null));
|
||||
currentFocus = null;
|
||||
});
|
||||
|
||||
//Set the focus of selected tag
|
||||
this.addEventFilter(MouseEvent.MOUSE_PRESSED, (MouseEvent e) -> {
|
||||
if (!e.isPrimaryButtonDown()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ImageTag selection = getTagToSelect(new Point2D(e.getX(), e.getY()));
|
||||
requestFocus(selection);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribe to focus change events on Image tags.
|
||||
*
|
||||
* @param fcl PCL to be notified which Image tag has been selected.
|
||||
*/
|
||||
public void addFocusChangeListener(PropertyChangeListener fcl) {
|
||||
this.pcs.addPropertyChangeListener(fcl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the image tag that current has focus.
|
||||
*
|
||||
* @return ImageTag instance or null if no tag is in focus.
|
||||
*/
|
||||
public ImageTag getFocus() {
|
||||
return currentFocus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the current focus
|
||||
*/
|
||||
public void clearFocus() {
|
||||
if(currentFocus != null) {
|
||||
resetFocus(currentFocus);
|
||||
currentFocus = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find which tag to select on a user mouse press. If multiple tags are
|
||||
* overlapping, pick the smallest one that is determined by the L + W of
|
||||
* the tag sides.
|
||||
*
|
||||
* @param coordinate User mouse press location
|
||||
* @return The tag to give focus
|
||||
*/
|
||||
private ImageTag getTagToSelect(Point2D coordinate) {
|
||||
ImageTag tagToSelect = null;
|
||||
double minTagSize = Double.MAX_VALUE;
|
||||
|
||||
//Find all intersecting tags, select the absolute min based on L + W.
|
||||
for (Node node : this.getChildren()) {
|
||||
ImageTag tag = (ImageTag) node;
|
||||
double tagSize = tag.getWidth() + tag.getHeight();
|
||||
if (tag.contains(coordinate) && tagSize < minTagSize) {
|
||||
tagToSelect = tag;
|
||||
minTagSize = tagSize;
|
||||
}
|
||||
}
|
||||
|
||||
return tagToSelect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the logical image tag that it is no longer in focus.
|
||||
*
|
||||
* @param n
|
||||
*/
|
||||
private void resetFocus(ImageTag n) {
|
||||
n.getEventDispatcher().dispatchEvent(new Event(ImageTagControls.NOT_FOCUSED), NO_OP_CHAIN);
|
||||
this.pcs.firePropertyChange(new PropertyChangeEvent(this, ImageTagControls.NOT_FOCUSED.getName(), n, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the logical image that it is in focus.
|
||||
*
|
||||
* @param n
|
||||
*/
|
||||
private void requestFocus(ImageTag n) {
|
||||
if (n == null || n.equals(currentFocus)) {
|
||||
return;
|
||||
} else if (currentFocus != null && !currentFocus.equals(n)) {
|
||||
resetFocus(currentFocus);
|
||||
}
|
||||
|
||||
n.getEventDispatcher().dispatchEvent(new Event(ImageTagControls.FOCUSED), NO_OP_CHAIN);
|
||||
this.pcs.firePropertyChange(new PropertyChangeEvent(this, ImageTagControls.FOCUSED.getName(), currentFocus, n));
|
||||
|
||||
currentFocus = n;
|
||||
n.toFront();
|
||||
}
|
||||
}
|
238
Core/src/org/sleuthkit/autopsy/contentviewers/imagetagging/ImageTagsUtil.java
Executable file
238
Core/src/org/sleuthkit/autopsy/contentviewers/imagetagging/ImageTagsUtil.java
Executable file
@ -0,0 +1,238 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> 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.contentviewers.imagetagging;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import javafx.concurrent.Task;
|
||||
import javafx.embed.swing.SwingFXUtils;
|
||||
import javafx.scene.image.Image;
|
||||
import javax.imageio.ImageIO;
|
||||
import org.opencv.core.Core;
|
||||
import org.opencv.core.Mat;
|
||||
import org.opencv.core.MatOfByte;
|
||||
import org.opencv.core.Point;
|
||||
import org.opencv.core.Scalar;
|
||||
import org.opencv.core.Size;
|
||||
import org.opencv.highgui.Highgui;
|
||||
import org.opencv.imgproc.Imgproc;
|
||||
import org.sleuthkit.autopsy.coreutils.ImageUtils;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.ReadContentInputStream;
|
||||
|
||||
/**
|
||||
* Utility for drawing rectangles on image files.
|
||||
*/
|
||||
public final class ImageTagsUtil {
|
||||
|
||||
//String constant for writing PNG in ImageIO
|
||||
private final static String AWT_PNG = "png";
|
||||
|
||||
//String constant for encoding PNG in OpenCV
|
||||
private final static String OPENCV_PNG = ".png";
|
||||
|
||||
/**
|
||||
* Creates an image with tags applied.
|
||||
*
|
||||
* @param file Source image.
|
||||
* @param tagRegions Tags to apply.
|
||||
* @return Tagged image.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws InterruptedException Calling thread was interrupted
|
||||
* @throws ExecutionException Error while reading image from AbstractFile
|
||||
*/
|
||||
public static BufferedImage getImageWithTags(AbstractFile file,
|
||||
Collection<ImageTagRegion> tagRegions) throws IOException, InterruptedException, ExecutionException {
|
||||
|
||||
//The raw image in OpenCV terms
|
||||
Mat sourceImage = getImageMatFromFile(file);
|
||||
//Image with tags in OpenCV terms
|
||||
MatOfByte taggedMatrix = getTaggedImageMatrix(sourceImage, tagRegions);
|
||||
|
||||
try (ByteArrayInputStream taggedStream = new ByteArrayInputStream(taggedMatrix.toArray())) {
|
||||
return ImageIO.read(taggedStream);
|
||||
} finally {
|
||||
sourceImage.release();
|
||||
taggedMatrix.release();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the image from file.
|
||||
*
|
||||
* @param file
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @throws InterruptedException
|
||||
* @throws ExecutionException
|
||||
*/
|
||||
private static BufferedImage getImageFromFile(AbstractFile file) throws IOException, InterruptedException, ExecutionException {
|
||||
if (ImageUtils.isGIF(file)) {
|
||||
//Grab the first frame.
|
||||
try (BufferedInputStream bufferedReadContentStream =
|
||||
new BufferedInputStream(new ReadContentInputStream(file))) {
|
||||
return ImageIO.read(bufferedReadContentStream);
|
||||
}
|
||||
} else {
|
||||
//Otherwise, read the full image.
|
||||
Task<Image> readImageTask = ImageUtils.newReadImageTask(file);
|
||||
readImageTask.run();
|
||||
Image fxResult = readImageTask.get();
|
||||
return SwingFXUtils.fromFXImage(fxResult, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the image and converts it into an OpenCV equivalent.
|
||||
*
|
||||
* @param file Image to read
|
||||
* @return raw image bytes
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws InterruptedException Calling thread was interrupted.
|
||||
* @throws ExecutionException Error while reading image from AbstractFile
|
||||
*/
|
||||
private static Mat getImageMatFromFile(AbstractFile file) throws InterruptedException, ExecutionException, IOException {
|
||||
//Get image from file
|
||||
BufferedImage buffImage = getImageFromFile(file);
|
||||
|
||||
//Convert it to OpenCV Mat.
|
||||
try (ByteArrayOutputStream outStream = new ByteArrayOutputStream()) {
|
||||
ImageIO.write(buffImage, AWT_PNG, outStream);
|
||||
|
||||
byte[] imageBytes = outStream.toByteArray();
|
||||
MatOfByte rawSourceBytes = new MatOfByte(imageBytes);
|
||||
Mat sourceImage = Highgui.imdecode(rawSourceBytes, Highgui.IMREAD_COLOR);
|
||||
rawSourceBytes.release();
|
||||
|
||||
return sourceImage;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds tags to an image matrix.
|
||||
*
|
||||
* @param sourceImage
|
||||
* @param tagRegions
|
||||
* @return
|
||||
*/
|
||||
private static MatOfByte getTaggedImageMatrix(Mat sourceImage, Collection<ImageTagRegion> tagRegions) {
|
||||
|
||||
//Apply all tags to source image
|
||||
for (ImageTagRegion region : tagRegions) {
|
||||
Point topLeft = new Point(region.getX(), region.getY());
|
||||
Point bottomRight = new Point(topLeft.x + region.getWidth(),
|
||||
topLeft.y + region.getHeight());
|
||||
//Red
|
||||
Scalar rectangleBorderColor = new Scalar(0, 0, 255);
|
||||
|
||||
int rectangleBorderWidth = (int) Math.rint(region.getStrokeThickness());
|
||||
|
||||
Core.rectangle(sourceImage, topLeft, bottomRight,
|
||||
rectangleBorderColor, rectangleBorderWidth);
|
||||
}
|
||||
|
||||
MatOfByte taggedMatrix = new MatOfByte();
|
||||
Highgui.imencode(OPENCV_PNG, sourceImage, taggedMatrix);
|
||||
|
||||
return taggedMatrix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a thumbnail with tags applied.
|
||||
*
|
||||
* @param file Input file to apply tags & produce thumbnail from
|
||||
* @param tagRegions Tags to apply
|
||||
* @param iconSize Size of the output thumbnail
|
||||
* @return BufferedImage Thumbnail image
|
||||
*
|
||||
* @throws InterruptedException Calling thread was interrupted.
|
||||
* @throws ExecutionException Error while reading image from file.
|
||||
*/
|
||||
public static BufferedImage getThumbnailWithTags(AbstractFile file, Collection<ImageTagRegion> tagRegions,
|
||||
IconSize iconSize) throws IOException, InterruptedException, ExecutionException {
|
||||
|
||||
//Raw image
|
||||
Mat sourceImage = getImageMatFromFile(file);
|
||||
//Full size image with tags
|
||||
MatOfByte taggedMatrix = getTaggedImageMatrix(sourceImage, tagRegions);
|
||||
//Resized to produce thumbnail
|
||||
MatOfByte thumbnailMatrix = getResizedMatrix(taggedMatrix, iconSize);
|
||||
|
||||
try (ByteArrayInputStream thumbnailStream = new ByteArrayInputStream(thumbnailMatrix.toArray())) {
|
||||
return ImageIO.read(thumbnailStream);
|
||||
} finally {
|
||||
sourceImage.release();
|
||||
taggedMatrix.release();
|
||||
thumbnailMatrix.release();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resizes the image matrix.
|
||||
*
|
||||
* @param taggedMatrix Image to resize.
|
||||
* @param size Size of thumbnail.
|
||||
*
|
||||
* @return A new resized image matrix.
|
||||
*/
|
||||
private static MatOfByte getResizedMatrix(MatOfByte taggedMatrix, IconSize size) {
|
||||
Size resizeDimensions = new Size(size.getSize(), size.getSize());
|
||||
Mat taggedImage = Highgui.imdecode(taggedMatrix, Highgui.IMREAD_COLOR);
|
||||
|
||||
Mat thumbnailImage = new Mat();
|
||||
Imgproc.resize(taggedImage, thumbnailImage, resizeDimensions);
|
||||
|
||||
MatOfByte thumbnailMatrix = new MatOfByte();
|
||||
Highgui.imencode(OPENCV_PNG, thumbnailImage, thumbnailMatrix);
|
||||
|
||||
thumbnailImage.release();
|
||||
taggedImage.release();
|
||||
|
||||
return thumbnailMatrix;
|
||||
}
|
||||
|
||||
private ImageTagsUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sizes for thumbnails
|
||||
*/
|
||||
public enum IconSize {
|
||||
SMALL(50),
|
||||
MEDIUM(100),
|
||||
LARGE(200);
|
||||
|
||||
private final int SIZE;
|
||||
|
||||
IconSize(int size) {
|
||||
this.SIZE = size;
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return SIZE;
|
||||
}
|
||||
}
|
||||
}
|
@ -23,6 +23,7 @@ import org.openide.nodes.Node;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
|
||||
/**
|
||||
* A DataContentViewer that displays text with the TextViewers available.
|
||||
@ -90,6 +91,17 @@ public class TextContentViewer implements DataContentViewer {
|
||||
if (node == null) {
|
||||
return false;
|
||||
}
|
||||
// get the node's File, if it has one
|
||||
AbstractFile file = node.getLookup().lookup(AbstractFile.class);
|
||||
if (file == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// disable the text content viewer for directories and empty files
|
||||
if (file.isDir() || file.getSize() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return panel.isSupported(node);
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ public class TextContentViewerPanel extends javax.swing.JPanel implements DataCo
|
||||
}
|
||||
|
||||
/**
|
||||
* Deterime wether the content viewer which displays this panel isSupported.
|
||||
* Determine whether the content viewer which displays this panel isSupported.
|
||||
* This panel is supported if any of the TextViewer's displayed in it are
|
||||
* supported.
|
||||
*
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user