mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-16 01:37:43 +00:00
Merge remote-tracking branch 'upstream/develop' into timeline-event-mgr
# Conflicts: # Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionFileIngestModule.java # RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chrome.java # RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractIE.java # RecentActivity/src/org/sleuthkit/autopsy/recentactivity/FirefoxExtractor.java # RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Util.java
This commit is contained in:
commit
1bbee98a78
@ -23,6 +23,8 @@
|
|||||||
<dependency conf="core->default" org="com.adobe.xmp" name="xmpcore" rev="5.1.2"/>
|
<dependency conf="core->default" org="com.adobe.xmp" name="xmpcore" rev="5.1.2"/>
|
||||||
<dependency conf="core->default" org="org.apache.zookeeper" name="zookeeper" rev="3.4.6"/>
|
<dependency conf="core->default" org="org.apache.zookeeper" name="zookeeper" rev="3.4.6"/>
|
||||||
|
|
||||||
|
<dependency conf="core->default" org="com.healthmarketscience.jackcess" name="jackcess" rev="2.2.0"/>
|
||||||
|
<dependency conf="core->default" org="com.healthmarketscience.jackcess" name="jackcess-encrypt" rev="2.1.4"/>
|
||||||
|
|
||||||
<dependency conf="core->default" org="org.apache.commons" name="commons-dbcp2" rev="2.1.1"/>
|
<dependency conf="core->default" org="org.apache.commons" name="commons-dbcp2" rev="2.1.1"/>
|
||||||
<dependency conf="core->default" org="org.apache.commons" name="commons-pool2" rev="2.4.2"/>
|
<dependency conf="core->default" org="org.apache.commons" name="commons-pool2" rev="2.4.2"/>
|
||||||
|
@ -18,8 +18,8 @@ file.reference.sevenzipjbinding.jar=release/modules/ext/sevenzipjbinding.jar
|
|||||||
file.reference.sqlite-jdbc-3.8.11.jar=release\\modules\\ext\\sqlite-jdbc-3.8.11.jar
|
file.reference.sqlite-jdbc-3.8.11.jar=release\\modules\\ext\\sqlite-jdbc-3.8.11.jar
|
||||||
file.reference.StixLib.jar=release/modules/ext/StixLib.jar
|
file.reference.StixLib.jar=release/modules/ext/StixLib.jar
|
||||||
file.reference.bcprov-jdk15on-1.54.jar=release/modules/ext/bcprov-jdk15on-1.54.jar
|
file.reference.bcprov-jdk15on-1.54.jar=release/modules/ext/bcprov-jdk15on-1.54.jar
|
||||||
file.reference.jackcess-2.1.8.jar=release/modules/ext/jackcess-2.1.8.jar
|
file.reference.jackcess-2.2.0.jar=release/modules/ext/jackcess-2.2.0.jar
|
||||||
file.reference.jackcess-encrypt-2.1.2.jar=release/modules/ext/jackcess-encrypt-2.1.2.jar
|
file.reference.jackcess-encrypt-2.1.4.jar=release/modules/ext/jackcess-encrypt-2.1.4.jar
|
||||||
file.reference.jempbox-1.8.13.jar=release/modules/ext/jempbox-1.8.13.jar
|
file.reference.jempbox-1.8.13.jar=release/modules/ext/jempbox-1.8.13.jar
|
||||||
file.reference.javax.ws.rs-api-2.0.1.jar=release/modules/ext/javax.ws.rs-api-2.0.1.jar
|
file.reference.javax.ws.rs-api-2.0.1.jar=release/modules/ext/javax.ws.rs-api-2.0.1.jar
|
||||||
file.reference.cxf-core-3.0.16.jar=release/modules/ext/cxf-core-3.0.16.jar
|
file.reference.cxf-core-3.0.16.jar=release/modules/ext/cxf-core-3.0.16.jar
|
||||||
@ -29,7 +29,7 @@ file.reference.cxf-rt-transports-http-3.0.16.jar=release/modules/ext/cxf-rt-tran
|
|||||||
file.reference.fontbox-2.0.8.jar=release/modules/ext/fontbox-2.0.8.jar
|
file.reference.fontbox-2.0.8.jar=release/modules/ext/fontbox-2.0.8.jar
|
||||||
file.reference.pdfbox-2.0.8.jar=release/modules/ext/pdfbox-2.0.8.jar
|
file.reference.pdfbox-2.0.8.jar=release/modules/ext/pdfbox-2.0.8.jar
|
||||||
file.reference.pdfbox-tools-2.0.8.jar=release/modules/ext/pdfbox-tools-2.0.8.jar
|
file.reference.pdfbox-tools-2.0.8.jar=release/modules/ext/pdfbox-tools-2.0.8.jar
|
||||||
file.reference.sleuthkit-postgresql-4.6.3.jar=release/modules/ext/sleuthkit-postgresql-4.6.3.jar
|
file.reference.sleuthkit-postgresql-4.6.4.jar=release/modules/ext/sleuthkit-postgresql-4.6.4.jar
|
||||||
file.reference.tika-core-1.17.jar=release/modules/ext/tika-core-1.17.jar
|
file.reference.tika-core-1.17.jar=release/modules/ext/tika-core-1.17.jar
|
||||||
file.reference.tika-parsers-1.17.jar=release/modules/ext/tika-parsers-1.17.jar
|
file.reference.tika-parsers-1.17.jar=release/modules/ext/tika-parsers-1.17.jar
|
||||||
file.reference.curator-client-2.8.0.jar=release/modules/ext/curator-client-2.8.0.jar
|
file.reference.curator-client-2.8.0.jar=release/modules/ext/curator-client-2.8.0.jar
|
||||||
|
@ -342,8 +342,8 @@
|
|||||||
<package>org.sleuthkit.datamodel</package>
|
<package>org.sleuthkit.datamodel</package>
|
||||||
</public-packages>
|
</public-packages>
|
||||||
<class-path-extension>
|
<class-path-extension>
|
||||||
<runtime-relative-path>ext/jackcess-2.1.8.jar</runtime-relative-path>
|
<runtime-relative-path>ext/jackcess-2.2.0.jar</runtime-relative-path>
|
||||||
<binary-origin>release/modules/ext/jackcess-2.1.8.jar</binary-origin>
|
<binary-origin>release/modules/ext/jackcess-2.2.0.jar</binary-origin>
|
||||||
</class-path-extension>
|
</class-path-extension>
|
||||||
<class-path-extension>
|
<class-path-extension>
|
||||||
<runtime-relative-path>ext/zookeeper-3.4.6.jar</runtime-relative-path>
|
<runtime-relative-path>ext/zookeeper-3.4.6.jar</runtime-relative-path>
|
||||||
@ -394,8 +394,8 @@
|
|||||||
<binary-origin>release/modules/ext/sevenzipjbinding.jar</binary-origin>
|
<binary-origin>release/modules/ext/sevenzipjbinding.jar</binary-origin>
|
||||||
</class-path-extension>
|
</class-path-extension>
|
||||||
<class-path-extension>
|
<class-path-extension>
|
||||||
<runtime-relative-path>ext/sleuthkit-postgresql-4.6.3.jar</runtime-relative-path>
|
<runtime-relative-path>ext/sleuthkit-postgresql-4.6.4.jar</runtime-relative-path>
|
||||||
<binary-origin>release/modules/ext/sleuthkit-postgresql-4.6.3.jar</binary-origin>
|
<binary-origin>release/modules/ext/sleuthkit-postgresql-4.6.4.jar</binary-origin>
|
||||||
</class-path-extension>
|
</class-path-extension>
|
||||||
<class-path-extension>
|
<class-path-extension>
|
||||||
<runtime-relative-path>ext/mchange-commons-java-0.2.9.jar</runtime-relative-path>
|
<runtime-relative-path>ext/mchange-commons-java-0.2.9.jar</runtime-relative-path>
|
||||||
@ -482,8 +482,8 @@
|
|||||||
<binary-origin>release\modules\ext\commons-pool2-2.4.2.jar</binary-origin>
|
<binary-origin>release\modules\ext\commons-pool2-2.4.2.jar</binary-origin>
|
||||||
</class-path-extension>
|
</class-path-extension>
|
||||||
<class-path-extension>
|
<class-path-extension>
|
||||||
<runtime-relative-path>ext/jackcess-encrypt-2.1.2.jar</runtime-relative-path>
|
<runtime-relative-path>ext/jackcess-encrypt-2.1.4.jar</runtime-relative-path>
|
||||||
<binary-origin>release/modules/ext/jackcess-encrypt-2.1.2.jar</binary-origin>
|
<binary-origin>release/modules/ext/jackcess-encrypt-2.1.4.jar</binary-origin>
|
||||||
</class-path-extension>
|
</class-path-extension>
|
||||||
<class-path-extension>
|
<class-path-extension>
|
||||||
<runtime-relative-path>ext/jsoup-1.10.3.jar</runtime-relative-path>
|
<runtime-relative-path>ext/jsoup-1.10.3.jar</runtime-relative-path>
|
||||||
|
@ -122,6 +122,7 @@ import org.sleuthkit.datamodel.SleuthkitCase;
|
|||||||
import org.sleuthkit.datamodel.TimelineManager;
|
import org.sleuthkit.datamodel.TimelineManager;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
import org.sleuthkit.datamodel.TskUnsupportedSchemaVersionException;
|
import org.sleuthkit.datamodel.TskUnsupportedSchemaVersionException;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.StopWatch;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An Autopsy case. Currently, only one case at a time may be open.
|
* An Autopsy case. Currently, only one case at a time may be open.
|
||||||
@ -743,11 +744,15 @@ public class Case {
|
|||||||
"Case.exceptionMessage.cannotGetLockToDeleteCase=Cannot delete case because it is open for another user or there is a problem with the coordination service."
|
"Case.exceptionMessage.cannotGetLockToDeleteCase=Cannot delete case because it is open for another user or there is a problem with the coordination service."
|
||||||
})
|
})
|
||||||
public static void deleteCase(CaseMetadata metadata) throws CaseActionException {
|
public static void deleteCase(CaseMetadata metadata) throws CaseActionException {
|
||||||
|
StopWatch stopWatch = new StopWatch();
|
||||||
|
stopWatch.start();
|
||||||
synchronized (caseActionSerializationLock) {
|
synchronized (caseActionSerializationLock) {
|
||||||
if (null != currentCase) {
|
if (null != currentCase) {
|
||||||
throw new CaseActionException(Bundle.Case_exceptionMessage_cannotDeleteCurrentCase());
|
throw new CaseActionException(Bundle.Case_exceptionMessage_cannotDeleteCurrentCase());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
stopWatch.stop();
|
||||||
|
logger.log(Level.INFO, String.format("Used %d s to acquire caseActionSerializationLock (Java monitor in Case class) for %s (%s) in %s", stopWatch.getElapsedTimeSecs(), metadata.getCaseDisplayName(), metadata.getCaseName(), metadata.getCaseDirectory()));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set up either a GUI progress indicator without a cancel button (can't
|
* Set up either a GUI progress indicator without a cancel button (can't
|
||||||
@ -769,10 +774,19 @@ public class Case {
|
|||||||
* cannot be deleted if another node has it open.
|
* cannot be deleted if another node has it open.
|
||||||
*/
|
*/
|
||||||
progressIndicator.progress(Bundle.Case_progressMessage_checkingForOtherUser());
|
progressIndicator.progress(Bundle.Case_progressMessage_checkingForOtherUser());
|
||||||
|
stopWatch.reset();
|
||||||
|
stopWatch.start();
|
||||||
try (CoordinationService.Lock dirLock = CoordinationService.getInstance().tryGetExclusiveLock(CategoryNode.CASES, metadata.getCaseDirectory())) {
|
try (CoordinationService.Lock dirLock = CoordinationService.getInstance().tryGetExclusiveLock(CategoryNode.CASES, metadata.getCaseDirectory())) {
|
||||||
assert (null != dirLock);
|
stopWatch.stop();
|
||||||
|
logger.log(Level.INFO, String.format("Used %d s to acquire case directory coordination service lock for %s (%s) in %s", stopWatch.getElapsedTimeSecs(), metadata.getCaseDisplayName(), metadata.getCaseName(), metadata.getCaseDirectory()));
|
||||||
|
if (dirLock != null) {
|
||||||
deleteCase(metadata, progressIndicator);
|
deleteCase(metadata, progressIndicator);
|
||||||
|
} else {
|
||||||
|
throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireDirLock());
|
||||||
|
}
|
||||||
} catch (CoordinationServiceException ex) {
|
} catch (CoordinationServiceException ex) {
|
||||||
|
stopWatch.stop();
|
||||||
|
logger.log(Level.INFO, String.format("Used %d s to fail to acquire case directory coordination service lock for %s (%s) in %s", stopWatch.getElapsedTimeSecs(), metadata.getCaseDisplayName(), metadata.getCaseName(), metadata.getCaseDirectory()));
|
||||||
throw new CaseActionException(Bundle.Case_exceptionMessage_cannotGetLockToDeleteCase(), ex);
|
throw new CaseActionException(Bundle.Case_exceptionMessage_cannotGetLockToDeleteCase(), ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -982,11 +996,13 @@ public class Case {
|
|||||||
"Case.exceptionMessage.errorsDeletingCase=Errors occured while deleting the case. See the application log for details"
|
"Case.exceptionMessage.errorsDeletingCase=Errors occured while deleting the case. See the application log for details"
|
||||||
})
|
})
|
||||||
private static void deleteCase(CaseMetadata metadata, ProgressIndicator progressIndicator) throws CaseActionException {
|
private static void deleteCase(CaseMetadata metadata, ProgressIndicator progressIndicator) throws CaseActionException {
|
||||||
|
StopWatch stopWatch = new StopWatch();
|
||||||
boolean errorsOccurred = false;
|
boolean errorsOccurred = false;
|
||||||
if (CaseType.MULTI_USER_CASE == metadata.getCaseType()) {
|
if (CaseType.MULTI_USER_CASE == metadata.getCaseType()) {
|
||||||
/*
|
/*
|
||||||
* Delete the case database from the database server.
|
* Delete the case database from the database server.
|
||||||
*/
|
*/
|
||||||
|
stopWatch.start();
|
||||||
try {
|
try {
|
||||||
progressIndicator.progress(Bundle.Case_progressMessage_deletingCaseDatabase());
|
progressIndicator.progress(Bundle.Case_progressMessage_deletingCaseDatabase());
|
||||||
CaseDbConnectionInfo db;
|
CaseDbConnectionInfo db;
|
||||||
@ -996,10 +1012,14 @@ public class Case {
|
|||||||
Statement statement = connection.createStatement();) {
|
Statement statement = connection.createStatement();) {
|
||||||
String deleteCommand = "DROP DATABASE \"" + metadata.getCaseDatabaseName() + "\""; //NON-NLS
|
String deleteCommand = "DROP DATABASE \"" + metadata.getCaseDatabaseName() + "\""; //NON-NLS
|
||||||
statement.execute(deleteCommand);
|
statement.execute(deleteCommand);
|
||||||
|
stopWatch.stop();
|
||||||
|
logger.log(Level.INFO, String.format("Used %d s to delete case database for %s (%s) in %s", stopWatch.getElapsedTimeSecs(), metadata.getCaseDisplayName(), metadata.getCaseName(), metadata.getCaseDirectory()));
|
||||||
}
|
}
|
||||||
} catch (UserPreferencesException | ClassNotFoundException | SQLException ex) {
|
} catch (UserPreferencesException | ClassNotFoundException | SQLException ex) {
|
||||||
logger.log(Level.SEVERE, String.format("Failed to delete case database %s for %s (%s) in %s", metadata.getCaseDatabaseName(), metadata.getCaseDisplayName(), metadata.getCaseName(), metadata.getCaseDirectory()), ex);
|
logger.log(Level.SEVERE, String.format("Failed to delete case database %s for %s (%s) in %s", metadata.getCaseDatabaseName(), metadata.getCaseDisplayName(), metadata.getCaseName(), metadata.getCaseDirectory()), ex);
|
||||||
errorsOccurred = true;
|
errorsOccurred = true;
|
||||||
|
stopWatch.stop();
|
||||||
|
logger.log(Level.INFO, String.format("Used %d s to fail delete case database for %s (%s) in %s", stopWatch.getElapsedTimeSecs(), metadata.getCaseDisplayName(), metadata.getCaseName(), metadata.getCaseDirectory()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1009,10 +1029,16 @@ public class Case {
|
|||||||
progressIndicator.progress(Bundle.Case_progressMessage_deletingTextIndex());
|
progressIndicator.progress(Bundle.Case_progressMessage_deletingTextIndex());
|
||||||
for (KeywordSearchService searchService : Lookup.getDefault().lookupAll(KeywordSearchService.class)) {
|
for (KeywordSearchService searchService : Lookup.getDefault().lookupAll(KeywordSearchService.class)) {
|
||||||
try {
|
try {
|
||||||
|
stopWatch.reset();
|
||||||
|
stopWatch.start();
|
||||||
searchService.deleteTextIndex(metadata);
|
searchService.deleteTextIndex(metadata);
|
||||||
|
stopWatch.stop();
|
||||||
|
logger.log(Level.INFO, String.format("Used %d s to delete text index for %s (%s) in %s", stopWatch.getElapsedTimeSecs(), metadata.getCaseDisplayName(), metadata.getCaseName(), metadata.getCaseDirectory()));
|
||||||
} catch (KeywordSearchServiceException ex) {
|
} catch (KeywordSearchServiceException ex) {
|
||||||
logger.log(Level.SEVERE, String.format("Failed to delete text index for %s (%s) in %s", metadata.getCaseDisplayName(), metadata.getCaseName(), metadata.getCaseDirectory()), ex);
|
logger.log(Level.SEVERE, String.format("Failed to delete text index for %s (%s) in %s", metadata.getCaseDisplayName(), metadata.getCaseName(), metadata.getCaseDirectory()), ex);
|
||||||
errorsOccurred = true;
|
errorsOccurred = true;
|
||||||
|
stopWatch.stop();
|
||||||
|
logger.log(Level.INFO, String.format("Used %d s to fail to delete text index for %s (%s) in %s", stopWatch.getElapsedTimeSecs(), metadata.getCaseDisplayName(), metadata.getCaseName(), metadata.getCaseDirectory()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1020,9 +1046,16 @@ public class Case {
|
|||||||
* Delete the case directory.
|
* Delete the case directory.
|
||||||
*/
|
*/
|
||||||
progressIndicator.progress(Bundle.Case_progressMessage_deletingCaseDirectory());
|
progressIndicator.progress(Bundle.Case_progressMessage_deletingCaseDirectory());
|
||||||
|
stopWatch.reset();
|
||||||
|
stopWatch.start();
|
||||||
if (!FileUtil.deleteDir(new File(metadata.getCaseDirectory()))) {
|
if (!FileUtil.deleteDir(new File(metadata.getCaseDirectory()))) {
|
||||||
logger.log(Level.SEVERE, String.format("Failed to delete case directory for %s (%s) in %s", metadata.getCaseDisplayName(), metadata.getCaseName(), metadata.getCaseDirectory()));
|
logger.log(Level.SEVERE, String.format("Failed to delete case directory for %s (%s) in %s", metadata.getCaseDisplayName(), metadata.getCaseName(), metadata.getCaseDirectory()));
|
||||||
errorsOccurred = true;
|
errorsOccurred = true;
|
||||||
|
stopWatch.stop();
|
||||||
|
logger.log(Level.INFO, String.format("Used %d s to fail to delete case directory for %s (%s) in %s", stopWatch.getElapsedTimeSecs(), metadata.getCaseDisplayName(), metadata.getCaseName(), metadata.getCaseDirectory()));
|
||||||
|
} else {
|
||||||
|
stopWatch.stop();
|
||||||
|
logger.log(Level.INFO, String.format("Used %d s to delete case directory for %s (%s) in %s", stopWatch.getElapsedTimeSecs(), metadata.getCaseDisplayName(), metadata.getCaseName(), metadata.getCaseDirectory()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1576,11 +1609,13 @@ public class Case {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies case event subscribers that a central repository comment has been changed.
|
* Notifies case event subscribers that a central repository comment has
|
||||||
|
* been changed.
|
||||||
*
|
*
|
||||||
* This should not be called from the event dispatch thread (EDT)
|
* This should not be called from the event dispatch thread (EDT)
|
||||||
*
|
*
|
||||||
* @param contentId the objectId for the Content which has had its central repo comment changed
|
* @param contentId the objectId for the Content which has had its central
|
||||||
|
* repo comment changed
|
||||||
* @param newComment the new value of the comment
|
* @param newComment the new value of the comment
|
||||||
*/
|
*/
|
||||||
public void notifyCentralRepoCommentChanged(long contentId, String newComment) {
|
public void notifyCentralRepoCommentChanged(long contentId, String newComment) {
|
||||||
@ -1836,7 +1871,7 @@ public class Case {
|
|||||||
progressIndicator.progress(Bundle.Case_progressMessage_preparingToOpenCaseResources());
|
progressIndicator.progress(Bundle.Case_progressMessage_preparingToOpenCaseResources());
|
||||||
acquireSharedCaseDirLock(metadata.getCaseDirectory());
|
acquireSharedCaseDirLock(metadata.getCaseDirectory());
|
||||||
try (CoordinationService.Lock resourcesLock = acquireExclusiveCaseResourcesLock(metadata.getCaseDirectory())) {
|
try (CoordinationService.Lock resourcesLock = acquireExclusiveCaseResourcesLock(metadata.getCaseDirectory())) {
|
||||||
assert (null != resourcesLock);
|
assert(resourcesLock != null); // Use reference to avoid compile time warning.
|
||||||
open(isNewCase, progressIndicator);
|
open(isNewCase, progressIndicator);
|
||||||
} catch (CaseActionException ex) {
|
} catch (CaseActionException ex) {
|
||||||
releaseSharedCaseDirLock(getMetadata().getCaseDirectory());
|
releaseSharedCaseDirLock(getMetadata().getCaseDirectory());
|
||||||
@ -2414,7 +2449,7 @@ public class Case {
|
|||||||
* @throws CaseActionException with a user-friendly message if the lock
|
* @throws CaseActionException with a user-friendly message if the lock
|
||||||
* cannot be acquired.
|
* cannot be acquired.
|
||||||
*/
|
*/
|
||||||
@Messages({"Case.creationException.couldNotAcquireDirLock=Failed to get lock on case directory."})
|
@Messages({"Case.creationException.couldNotAcquireDirLock=Failed to get lock on case directory"})
|
||||||
private void acquireSharedCaseDirLock(String caseDir) throws CaseActionException {
|
private void acquireSharedCaseDirLock(String caseDir) throws CaseActionException {
|
||||||
try {
|
try {
|
||||||
caseDirLock = CoordinationService.getInstance().tryGetSharedLock(CategoryNode.CASES, caseDir, DIR_LOCK_TIMOUT_HOURS, TimeUnit.HOURS);
|
caseDirLock = CoordinationService.getInstance().tryGetSharedLock(CategoryNode.CASES, caseDir, DIR_LOCK_TIMOUT_HOURS, TimeUnit.HOURS);
|
||||||
|
@ -21,8 +21,6 @@ package org.sleuthkit.autopsy.casemodule;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.SimpleTimeZone;
|
|
||||||
import java.util.TimeZone;
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import javax.swing.JFileChooser;
|
import javax.swing.JFileChooser;
|
||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
@ -39,6 +37,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
|||||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||||
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
|
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
|
||||||
import org.sleuthkit.autopsy.coreutils.PathValidator;
|
import org.sleuthkit.autopsy.coreutils.PathValidator;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.TimeZoneUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Panel for adding an image file such as .img, .E0x, .00x, etc. Allows the user
|
* Panel for adding an image file such as .img, .E0x, .00x, etc. Allows the user
|
||||||
@ -72,11 +71,7 @@ public class ImageFilePanel extends JPanel implements DocumentListener {
|
|||||||
initComponents();
|
initComponents();
|
||||||
|
|
||||||
// Populate the drop down list of time zones
|
// Populate the drop down list of time zones
|
||||||
for (String id : SimpleTimeZone.getAvailableIDs()) {
|
createTimeZoneList();
|
||||||
timeZoneComboBox.addItem(timeZoneToString(TimeZone.getTimeZone(id)));
|
|
||||||
}
|
|
||||||
// set the selected timezone to the current timezone
|
|
||||||
timeZoneComboBox.setSelectedItem(timeZoneToString(Calendar.getInstance().getTimeZone()));
|
|
||||||
|
|
||||||
// Populate the drop down list of sector size options
|
// Populate the drop down list of sector size options
|
||||||
for (String choice : SECTOR_SIZE_CHOICES) {
|
for (String choice : SECTOR_SIZE_CHOICES) {
|
||||||
@ -95,6 +90,20 @@ public class ImageFilePanel extends JPanel implements DocumentListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the drop down list for the time zones and defaults the selection
|
||||||
|
* to the local machine time zone.
|
||||||
|
*/
|
||||||
|
private void createTimeZoneList() {
|
||||||
|
List<String> timeZoneList = TimeZoneUtils.createTimeZoneList();
|
||||||
|
for (String timeZone : timeZoneList) {
|
||||||
|
timeZoneComboBox.addItem(timeZone);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the selected timezone
|
||||||
|
timeZoneComboBox.setSelectedItem(TimeZoneUtils.createTimeZoneString(Calendar.getInstance().getTimeZone()));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates and returns an instance of a ImageFilePanel.
|
* Creates and returns an instance of a ImageFilePanel.
|
||||||
*
|
*
|
||||||
@ -348,21 +357,6 @@ public class ImageFilePanel extends JPanel implements DocumentListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a string representation of a TimeZone for use in the drop down list.
|
|
||||||
*
|
|
||||||
* @param zone The TimeZone to make a string for
|
|
||||||
*
|
|
||||||
* @return A string representation of a TimeZone for use in the drop down
|
|
||||||
* list.
|
|
||||||
*/
|
|
||||||
static private String timeZoneToString(TimeZone zone) {
|
|
||||||
int offset = zone.getRawOffset() / 1000;
|
|
||||||
int hour = offset / 3600;
|
|
||||||
int minutes = (offset % 3600) / 60;
|
|
||||||
return String.format("(GMT%+d:%02d) %s", hour, minutes, zone.getID()); //NON-NLS
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void insertUpdate(DocumentEvent e) {
|
public void insertUpdate(DocumentEvent e) {
|
||||||
updateHelper();
|
updateHelper();
|
||||||
|
@ -21,8 +21,7 @@ package org.sleuthkit.autopsy.casemodule;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.SimpleTimeZone;
|
import java.util.List;
|
||||||
import java.util.TimeZone;
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import javax.swing.JFileChooser;
|
import javax.swing.JFileChooser;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
@ -32,6 +31,7 @@ import org.sleuthkit.autopsy.coreutils.LocalDisk;
|
|||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||||
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.TimeZoneUtils;
|
||||||
import org.sleuthkit.autopsy.imagewriter.ImageWriterSettings;
|
import org.sleuthkit.autopsy.imagewriter.ImageWriterSettings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -469,36 +469,13 @@ final class LocalDiskPanel extends JPanel {
|
|||||||
* to the local machine time zone.
|
* to the local machine time zone.
|
||||||
*/
|
*/
|
||||||
public void createTimeZoneList() {
|
public void createTimeZoneList() {
|
||||||
// load and add all timezone
|
List<String> timeZoneList = TimeZoneUtils.createTimeZoneList();
|
||||||
String[] ids = SimpleTimeZone.getAvailableIDs();
|
for (String timeZone : timeZoneList) {
|
||||||
for (String id : ids) {
|
timeZoneComboBox.addItem(timeZone);
|
||||||
TimeZone zone = TimeZone.getTimeZone(id);
|
|
||||||
int offset = zone.getRawOffset() / 1000;
|
|
||||||
int hour = offset / 3600;
|
|
||||||
int minutes = (offset % 3600) / 60;
|
|
||||||
String item = String.format("(GMT%+d:%02d) %s", hour, minutes, id); //NON-NLS
|
|
||||||
|
|
||||||
/*
|
|
||||||
* DateFormat dfm = new SimpleDateFormat("z");
|
|
||||||
* dfm.setTimeZone(zone); boolean hasDaylight =
|
|
||||||
* zone.useDaylightTime(); String first = dfm.format(new Date(2010,
|
|
||||||
* 1, 1)); String second = dfm.format(new Date(2011, 6, 6)); int mid
|
|
||||||
* = hour * -1; String result = first + Integer.toString(mid);
|
|
||||||
* if(hasDaylight){ result = result + second; }
|
|
||||||
* timeZoneComboBox.addItem(item + " (" + result + ")");
|
|
||||||
*/
|
|
||||||
timeZoneComboBox.addItem(item);
|
|
||||||
}
|
}
|
||||||
// get the current timezone
|
|
||||||
TimeZone thisTimeZone = Calendar.getInstance().getTimeZone();
|
|
||||||
int thisOffset = thisTimeZone.getRawOffset() / 1000;
|
|
||||||
int thisHour = thisOffset / 3600;
|
|
||||||
int thisMinutes = (thisOffset % 3600) / 60;
|
|
||||||
String formatted = String.format("(GMT%+d:%02d) %s", thisHour, thisMinutes, thisTimeZone.getID()); //NON-NLS
|
|
||||||
|
|
||||||
// set the selected timezone
|
// set the selected timezone
|
||||||
timeZoneComboBox.setSelectedItem(formatted);
|
timeZoneComboBox.setSelectedItem(TimeZoneUtils.createTimeZoneString(Calendar.getInstance().getTimeZone()));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -369,7 +369,7 @@ public class LocalFilesDSProcessor implements DataSourceProcessor, AutoIngestDat
|
|||||||
@Override
|
@Override
|
||||||
public void process(String deviceId, Path dataSourcePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
|
public void process(String deviceId, Path dataSourcePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
|
||||||
List<String> filePaths = Arrays.asList(new String[]{dataSourcePath.toString()});
|
List<String> filePaths = Arrays.asList(new String[]{dataSourcePath.toString()});
|
||||||
run(deviceId, deviceId, filePaths, progressMonitor, callBack);
|
run(deviceId, "", filePaths, progressMonitor, callBack);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -492,6 +492,7 @@ public class FileManager implements Closeable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
trans.commit();
|
trans.commit();
|
||||||
|
trans = null;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Publish content added events for the added files and directories.
|
* Publish content added events for the added files and directories.
|
||||||
@ -502,15 +503,14 @@ public class FileManager implements Closeable {
|
|||||||
|
|
||||||
return dataSource;
|
return dataSource;
|
||||||
|
|
||||||
} catch (TskCoreException ex) {
|
} finally {
|
||||||
if (null != trans) {
|
if (null != trans) {
|
||||||
try {
|
try {
|
||||||
trans.rollback();
|
trans.rollback();
|
||||||
} catch (TskCoreException ex2) {
|
} catch (TskCoreException ex) {
|
||||||
LOGGER.log(Level.SEVERE, String.format("Failed to rollback transaction after exception: %s", ex.getMessage()), ex2);
|
LOGGER.log(Level.SEVERE, "Failed to rollback transaction after exception", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw ex;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2960,14 +2960,10 @@ abstract class AbstractSqlEamDb implements EamDb {
|
|||||||
resultSet.getString("poc_phone"));
|
resultSet.getString("poc_phone"));
|
||||||
}
|
}
|
||||||
|
|
||||||
CorrelationCase eamCase = new CorrelationCase(resultSet.getInt("case_id"), resultSet.getString("case_uid"), resultSet.getString("case_name"));
|
CorrelationCase eamCase = new CorrelationCase(resultSet.getInt("case_id"), resultSet.getString("case_uid"), eamOrg, resultSet.getString("case_name"),
|
||||||
eamCase.setOrg(eamOrg);
|
resultSet.getString("creation_date"), resultSet.getString("case_number"), resultSet.getString("examiner_name"),
|
||||||
eamCase.setCreationDate(resultSet.getString("creation_date"));
|
resultSet.getString("examiner_email"), resultSet.getString("examiner_phone"), resultSet.getString("notes"));
|
||||||
eamCase.setCaseNumber(resultSet.getString("case_number"));
|
|
||||||
eamCase.setExaminerName(resultSet.getString("examiner_name"));
|
|
||||||
eamCase.setExaminerEmail(resultSet.getString("examiner_email"));
|
|
||||||
eamCase.setExaminerPhone(resultSet.getString("examiner_phone"));
|
|
||||||
eamCase.setNotes(resultSet.getString("notes"));
|
|
||||||
|
|
||||||
return eamCase;
|
return eamCase;
|
||||||
}
|
}
|
||||||
@ -3017,7 +3013,6 @@ abstract class AbstractSqlEamDb implements EamDb {
|
|||||||
if (null == resultSet) {
|
if (null == resultSet) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// @@@ We should have data source ID in the previous query instead of passing -1 into the below constructor
|
|
||||||
return new CorrelationAttributeInstance(
|
return new CorrelationAttributeInstance(
|
||||||
aType,
|
aType,
|
||||||
resultSet.getString("value"),
|
resultSet.getString("value"),
|
||||||
|
@ -66,7 +66,7 @@ GlobalSettingsPanel.lbCentralRepository.text=A central repository allows you to
|
|||||||
GlobalSettingsPanel.pnCorrelationProperties.border.title=Correlation Properties
|
GlobalSettingsPanel.pnCorrelationProperties.border.title=Correlation Properties
|
||||||
GlobalSettingsPanel.organizationPanel.border.title=Organizations
|
GlobalSettingsPanel.organizationPanel.border.title=Organizations
|
||||||
GlobalSettingsPanel.casesPanel.border.title=Case Details
|
GlobalSettingsPanel.casesPanel.border.title=Case Details
|
||||||
GlobalSettingsPanel.showCasesButton.text=Show Cases
|
GlobalSettingsPanel.showCasesButton.text=Manage Cases
|
||||||
ShowCasesDialog.closeButton.AccessibleContext.accessibleName=Close
|
ShowCasesDialog.closeButton.AccessibleContext.accessibleName=Close
|
||||||
ShowCasesDialog.closeButton.actionCommand=Close
|
ShowCasesDialog.closeButton.actionCommand=Close
|
||||||
ShowCasesDialog.closeButton.text=Close
|
ShowCasesDialog.closeButton.text=Close
|
||||||
@ -76,3 +76,12 @@ GlobalSettingsPanel.Case\ Details.AccessibleContext.accessibleName=Cases Details
|
|||||||
ShowCasesDialog.caseDetailsTable.AccessibleContext.accessibleDescription=Click column name to sort.
|
ShowCasesDialog.caseDetailsTable.AccessibleContext.accessibleDescription=Click column name to sort.
|
||||||
GlobalSettingsPanel.casesTextArea.text=Display table that lists central repository case details.
|
GlobalSettingsPanel.casesTextArea.text=Display table that lists central repository case details.
|
||||||
GlobalSettingsPanel.ingestRunningWarningLabel.text=Cannot make changes to central repository settings when ingest is running!
|
GlobalSettingsPanel.ingestRunningWarningLabel.text=Cannot make changes to central repository settings when ingest is running!
|
||||||
|
ManageCasesDialog.examinerPhoneLabel.text=Examiner Phone:
|
||||||
|
ManageCasesDialog.examinerNameLabel.text=Examiner Name:
|
||||||
|
ManageCasesDialog.examinerEmailLabel.text=Examiner Email:
|
||||||
|
ManageCasesDialog.caseNumberLabel.text=Case Number:
|
||||||
|
ManageCasesDialog.orgLabel.text=Organization:
|
||||||
|
ManageCasesDialog.closeButton.text=Close
|
||||||
|
ManageCasesDialog.notesLabel.text=Notes:
|
||||||
|
ManageCasesDialog.dataSourcesLabel.text=Data Sources:
|
||||||
|
ManageCasesDialog.caseInfoLabel.text=Case Info:
|
||||||
|
@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* Central Repository
|
||||||
|
*
|
||||||
|
* Copyright 2018 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.centralrepository.optionspanel;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationDataSource;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.EamOrganization;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object to contain both a CorrelationCase and the list of
|
||||||
|
* CorrelationDataSources which are associated with that case.
|
||||||
|
*/
|
||||||
|
class CaseDataSourcesWrapper {
|
||||||
|
|
||||||
|
private final CorrelationCase eamCase;
|
||||||
|
private final List<CorrelationDataSource> dataSources;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new CaseDataSourcesWrapper object.
|
||||||
|
*
|
||||||
|
* @param correlationCase - the CorrelationCase which is being represented
|
||||||
|
* @param dataSourceList - the list of CorrelationDataSource objects which
|
||||||
|
* are associated with the CorrelationCase
|
||||||
|
*/
|
||||||
|
CaseDataSourcesWrapper(CorrelationCase correlationCase, List<CorrelationDataSource> dataSourceList) {
|
||||||
|
eamCase = correlationCase;
|
||||||
|
dataSources = dataSourceList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the display name of the CorrelationCase.
|
||||||
|
*
|
||||||
|
* @return the display name of the CorrelationCase.
|
||||||
|
*/
|
||||||
|
String getDisplayName() {
|
||||||
|
return eamCase.getDisplayName();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of CorrelationDataSources associated with the
|
||||||
|
* CorrelationCase.
|
||||||
|
*
|
||||||
|
* @return the list of CorrelationDataSources associated with the
|
||||||
|
* CorrelationCase.
|
||||||
|
*/
|
||||||
|
List<CorrelationDataSource> getDataSources() {
|
||||||
|
return Collections.unmodifiableList(dataSources);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the creation date of the CorrelationCase.
|
||||||
|
*
|
||||||
|
* @return the creation date of the CorrelationCase.
|
||||||
|
*/
|
||||||
|
String getCreationDate() {
|
||||||
|
return eamCase.getCreationDate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the organization name of the CorrelationCase.
|
||||||
|
*
|
||||||
|
* @return the organization name of the CorrelationCase.
|
||||||
|
*/
|
||||||
|
String getOrganizationName() {
|
||||||
|
EamOrganization org = eamCase.getOrg();
|
||||||
|
return org == null ? "" : org.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the case number of the CorrelationCase.
|
||||||
|
*
|
||||||
|
* @return the case number of the CorrelationCase.
|
||||||
|
*/
|
||||||
|
String getCaseNumber() {
|
||||||
|
return eamCase.getCaseNumber();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the examiner name of the CorrelationCase.
|
||||||
|
*
|
||||||
|
* @return the examiner name of the CorrelationCase.
|
||||||
|
*/
|
||||||
|
String getExaminerName() {
|
||||||
|
return eamCase.getExaminerName();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the examiner email of the CorrelationCase.
|
||||||
|
*
|
||||||
|
* @return the examiner email of the CorrelationCase.
|
||||||
|
*/
|
||||||
|
String getExaminerEmail() {
|
||||||
|
return eamCase.getExaminerEmail();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the notes of the CorrelationCase.
|
||||||
|
*
|
||||||
|
* @return the notes of the CorrelationCase.
|
||||||
|
*/
|
||||||
|
String getNotes() {
|
||||||
|
return eamCase.getNotes();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the examiner phone number of the CorrelationCase.
|
||||||
|
*
|
||||||
|
* @return the examiner phone number of the CorrelationCase.
|
||||||
|
*/
|
||||||
|
String getExaminerPhone() {
|
||||||
|
return eamCase.getExaminerPhone();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,156 @@
|
|||||||
|
/*
|
||||||
|
* Central Repository
|
||||||
|
*
|
||||||
|
* Copyright 2018 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.centralrepository.optionspanel;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.swing.table.AbstractTableModel;
|
||||||
|
import org.openide.util.NbBundle.Messages;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationDataSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Model for cells to display correlation case information
|
||||||
|
*/
|
||||||
|
class CasesTableModel extends AbstractTableModel {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list of Eam Cases from central repository.
|
||||||
|
*/
|
||||||
|
private final List<CaseDataSourcesWrapper> eamCases;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Model for cells to display correlation case information
|
||||||
|
*/
|
||||||
|
CasesTableModel() {
|
||||||
|
eamCases = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getColumnCount() {
|
||||||
|
return CaseTableColumns.values().length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRowCount() {
|
||||||
|
return eamCases.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getColumnName(int colIdx) {
|
||||||
|
return CaseTableColumns.values()[colIdx].columnName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getValueAt(int rowIdx, int colIdx) {
|
||||||
|
if (eamCases.isEmpty()) {
|
||||||
|
return Bundle.CasesTableModel_noData();
|
||||||
|
}
|
||||||
|
|
||||||
|
return mapValueById(rowIdx, CaseTableColumns.values()[colIdx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map a rowIdx and colId to the value in that cell.
|
||||||
|
*
|
||||||
|
* @param rowIdx Index of row to search
|
||||||
|
* @param colId ID of column to search
|
||||||
|
*
|
||||||
|
* @return value in the cell
|
||||||
|
*/
|
||||||
|
@Messages({"CasesTableModel.noData=No Cases"})
|
||||||
|
private Object mapValueById(int rowIdx, CaseTableColumns colId) {
|
||||||
|
CaseDataSourcesWrapper eamCase = eamCases.get(rowIdx);
|
||||||
|
String value = Bundle.CasesTableModel_noData();
|
||||||
|
|
||||||
|
switch (colId) {
|
||||||
|
case CASE_NAME:
|
||||||
|
value = eamCase.getDisplayName();
|
||||||
|
break;
|
||||||
|
case CREATION_DATE:
|
||||||
|
value = eamCase.getCreationDate();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<String> getColumnClass(int colIdx) {
|
||||||
|
return String.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add one local central repository case to the table.
|
||||||
|
*
|
||||||
|
* @param eamCase central repository case to add to the table
|
||||||
|
*/
|
||||||
|
void addEamCase(CorrelationCase eamCase, List<CorrelationDataSource> dataSourceList) {
|
||||||
|
eamCases.add(new CaseDataSourcesWrapper(eamCase, dataSourceList));
|
||||||
|
fireTableDataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the CaseDataSourcesWrapper for the specified index in the table.
|
||||||
|
*
|
||||||
|
* @param listIndex the idex of the object to get
|
||||||
|
*
|
||||||
|
* @return A caseDataSourcesWrapper containing the CorrelationCase and the
|
||||||
|
* CorrelationDataSources associated with it for the specified
|
||||||
|
* index.
|
||||||
|
*/
|
||||||
|
CaseDataSourcesWrapper getEamCase(int listIndex) {
|
||||||
|
return eamCases.get(listIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum which lists columns of interest from CorrelationCase.
|
||||||
|
*/
|
||||||
|
@Messages({"CasesTableModel.case=Case Name",
|
||||||
|
"CasesTableModel.creationDate=Creation Date"})
|
||||||
|
private enum CaseTableColumns {
|
||||||
|
// Ordering here determines displayed column order in Content Viewer.
|
||||||
|
// If order is changed, update the CellRenderer to ensure correct row coloring.
|
||||||
|
CASE_NAME(Bundle.CasesTableModel_case()),
|
||||||
|
CREATION_DATE(Bundle.CasesTableModel_creationDate());
|
||||||
|
|
||||||
|
private final String columnName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make a DataSourceTableColumns enum item.
|
||||||
|
*
|
||||||
|
* @param columnName the name of the column.s
|
||||||
|
*/
|
||||||
|
CaseTableColumns(String columnName) {
|
||||||
|
this.columnName = columnName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name displayed in the column header.
|
||||||
|
*
|
||||||
|
* @return the name of the column.
|
||||||
|
*/
|
||||||
|
String columnName() {
|
||||||
|
return columnName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,152 @@
|
|||||||
|
/*
|
||||||
|
* Central Repository
|
||||||
|
*
|
||||||
|
* Copyright 2018 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.centralrepository.optionspanel;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.swing.table.AbstractTableModel;
|
||||||
|
import org.openide.util.NbBundle.Messages;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationDataSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Model for cells to display correlation data source information
|
||||||
|
*/
|
||||||
|
class DataSourcesTableModel extends AbstractTableModel {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list of correlation data sources from central repository.
|
||||||
|
*/
|
||||||
|
private final List<CorrelationDataSource> dataSources;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new DataSourcesTableModel, with an initially empty list of data
|
||||||
|
* sources.
|
||||||
|
*/
|
||||||
|
DataSourcesTableModel() {
|
||||||
|
dataSources = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getColumnCount() {
|
||||||
|
return DataSourcesTableColumns.values().length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRowCount() {
|
||||||
|
return dataSources.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getColumnName(int colIdx) {
|
||||||
|
return DataSourcesTableColumns.values()[colIdx].columnName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getValueAt(int rowIdx, int colIdx) {
|
||||||
|
if (dataSources.isEmpty()) {
|
||||||
|
return Bundle.DataSourcesTableModel_noData();
|
||||||
|
}
|
||||||
|
|
||||||
|
return mapValueById(rowIdx, DataSourcesTableColumns.values()[colIdx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map a rowIdx and colId to the value in that cell.
|
||||||
|
*
|
||||||
|
* @param rowIdx Index of row to search
|
||||||
|
* @param colId ID of column to search
|
||||||
|
*
|
||||||
|
* @return value in the cell
|
||||||
|
*/
|
||||||
|
@Messages({"DataSourcesTableModel.noData=No Data Sources"})
|
||||||
|
private Object mapValueById(int rowIdx, DataSourcesTableColumns colId) {
|
||||||
|
CorrelationDataSource dataSource = dataSources.get(rowIdx);
|
||||||
|
String value = Bundle.DataSourcesTableModel_noData();
|
||||||
|
|
||||||
|
switch (colId) {
|
||||||
|
case DATA_SOURCE:
|
||||||
|
value = dataSource.getName();
|
||||||
|
break;
|
||||||
|
case DEVICE_ID:
|
||||||
|
value = dataSource.getDeviceID();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<String> getColumnClass(int colIdx) {
|
||||||
|
return String.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a list of datasources to the table.
|
||||||
|
*
|
||||||
|
* @param dataSourceList the list of datasources to add to the table
|
||||||
|
*/
|
||||||
|
void addDataSources(List<CorrelationDataSource> dataSourceList) {
|
||||||
|
dataSources.addAll(dataSourceList);
|
||||||
|
fireTableDataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the data sources currently included in the model.
|
||||||
|
*/
|
||||||
|
void clearTable() {
|
||||||
|
dataSources.clear();
|
||||||
|
fireTableDataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Messages({"DataSourcesTableModel.dataSource=Data Source Name",
|
||||||
|
"DataSourcesTableModel.deviceId=Device ID"})
|
||||||
|
/**
|
||||||
|
* Enum which lists columns of interest from CorrelationDataSource.
|
||||||
|
*/
|
||||||
|
private enum DataSourcesTableColumns {
|
||||||
|
// Ordering here determines displayed column order in Content Viewer.
|
||||||
|
// If order is changed, update the CellRenderer to ensure correct row coloring.
|
||||||
|
DATA_SOURCE(Bundle.DataSourcesTableModel_dataSource()),
|
||||||
|
DEVICE_ID(Bundle.DataSourcesTableModel_deviceId());
|
||||||
|
|
||||||
|
private final String columnName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make a CasesTableColumns enum item.
|
||||||
|
*
|
||||||
|
* @param columnName the name of the column.
|
||||||
|
*/
|
||||||
|
DataSourcesTableColumns(String columnName) {
|
||||||
|
this.columnName = columnName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name displayed in the column header.
|
||||||
|
*
|
||||||
|
* @return the name of the column.
|
||||||
|
*/
|
||||||
|
String columnName() {
|
||||||
|
return columnName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -441,7 +441,7 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
|
|||||||
|
|
||||||
private void showCasesButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showCasesButtonActionPerformed
|
private void showCasesButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showCasesButtonActionPerformed
|
||||||
store();
|
store();
|
||||||
ShowCasesDialog showCasesDialog = new ShowCasesDialog();
|
ManageCasesDialog.displayManageCasesDialog();
|
||||||
}//GEN-LAST:event_showCasesButtonActionPerformed
|
}//GEN-LAST:event_showCasesButtonActionPerformed
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -0,0 +1,358 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
|
<Form version="1.6" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
|
||||||
|
<Properties>
|
||||||
|
<Property name="defaultCloseOperation" type="int" value="2"/>
|
||||||
|
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[400, 400]"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<SyntheticProperties>
|
||||||
|
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
|
||||||
|
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
|
||||||
|
</SyntheticProperties>
|
||||||
|
<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="casesSplitPane" alignment="1" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
<DimensionLayout dim="1">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Component id="casesSplitPane" alignment="0" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
</Layout>
|
||||||
|
<SubComponents>
|
||||||
|
<Container class="javax.swing.JSplitPane" name="casesSplitPane">
|
||||||
|
<Properties>
|
||||||
|
<Property name="dividerLocation" type="int" value="380"/>
|
||||||
|
</Properties>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
|
||||||
|
<SubComponents>
|
||||||
|
<Container class="javax.swing.JPanel" name="caseInfoPanel">
|
||||||
|
<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>
|
||||||
|
|
||||||
|
<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">
|
||||||
|
<Group type="102" attributes="0">
|
||||||
|
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
|
||||||
|
<Component id="dataSourcesScrollPane" pref="0" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<Group type="102" alignment="0" attributes="0">
|
||||||
|
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Group type="102" attributes="0">
|
||||||
|
<Group type="103" groupAlignment="1" attributes="0">
|
||||||
|
<Component id="orgLabel" min="-2" pref="88" max="-2" attributes="0"/>
|
||||||
|
<Component id="caseNumberLabel" min="-2" pref="88" max="-2" attributes="0"/>
|
||||||
|
<Component id="examinerNameLabel" alignment="1" min="-2" pref="88" max="-2" attributes="0"/>
|
||||||
|
<Component id="examinerEmailLabel" alignment="1" min="-2" pref="88" max="-2" attributes="0"/>
|
||||||
|
<Component id="examinerPhoneLabel" alignment="1" min="-2" pref="88" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<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="caseNumberValueLabel" max="32767" attributes="0"/>
|
||||||
|
<Component id="orgValueLabel" alignment="0" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
<Group type="102" alignment="0" attributes="0">
|
||||||
|
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Component id="examinerNameValueLabel" max="32767" attributes="0"/>
|
||||||
|
<Component id="examinerEmailValueLabel" max="32767" attributes="0"/>
|
||||||
|
<Component id="examinerPhoneValueLabel" alignment="0" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
<Component id="notesLabel" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Group type="102" attributes="0">
|
||||||
|
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
|
||||||
|
<Component id="notesScrollPane" pref="428" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
<Group type="102" alignment="1" attributes="0">
|
||||||
|
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||||
|
<Component id="closeButton" min="-2" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<Group type="102" attributes="0">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Component id="caseInfoLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="dataSourcesLabel" alignment="0" min="-2" pref="77" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<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="1" attributes="0">
|
||||||
|
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="caseInfoLabel" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||||
|
<Group type="103" groupAlignment="1" attributes="0">
|
||||||
|
<Group type="102" attributes="0">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Group type="102" alignment="0" attributes="0">
|
||||||
|
<Component id="orgLabel" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||||
|
<Component id="caseNumberLabel" max="32767" attributes="0"/>
|
||||||
|
<Component id="caseNumberValueLabel" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||||
|
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||||
|
<Component id="examinerNameLabel" max="32767" attributes="0"/>
|
||||||
|
<Component id="examinerNameValueLabel" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
<Component id="orgValueLabel" alignment="0" min="-2" pref="14" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="examinerEmailLabel" min="-2" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<Component id="examinerEmailValueLabel" min="-2" pref="14" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Component id="examinerPhoneLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="examinerPhoneValueLabel" alignment="0" min="-2" pref="14" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="notesLabel" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="notesScrollPane" pref="55" max="32767" attributes="0"/>
|
||||||
|
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="dataSourcesLabel" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="dataSourcesScrollPane" pref="129" max="32767" attributes="0"/>
|
||||||
|
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="closeButton" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
</Layout>
|
||||||
|
<SubComponents>
|
||||||
|
<Container class="javax.swing.JScrollPane" name="dataSourcesScrollPane">
|
||||||
|
<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.JTable" name="dataSourcesTable">
|
||||||
|
<Properties>
|
||||||
|
<Property name="autoCreateRowSorter" type="boolean" value="true"/>
|
||||||
|
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||||
|
<Connection code="dataSourcesTableModel" type="code"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor">
|
||||||
|
<JTableSelectionModel selectionMode="0"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_SerializeTo" type="java.lang.String" value="CaseManagerDialog_dataSourcesTable"/>
|
||||||
|
</AuxValues>
|
||||||
|
</Component>
|
||||||
|
</SubComponents>
|
||||||
|
</Container>
|
||||||
|
<Container class="javax.swing.JScrollPane" name="notesScrollPane">
|
||||||
|
<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="notesTextArea">
|
||||||
|
<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"/>
|
||||||
|
<Property name="wrapStyleWord" type="boolean" value="true"/>
|
||||||
|
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||||
|
<Border info="null"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
</SubComponents>
|
||||||
|
</Container>
|
||||||
|
<Component class="javax.swing.JLabel" name="caseInfoLabel">
|
||||||
|
<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="ManageCasesDialog.caseInfoLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="dataSourcesLabel">
|
||||||
|
<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="ManageCasesDialog.dataSourcesLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="notesLabel">
|
||||||
|
<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="ManageCasesDialog.notesLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="orgLabel">
|
||||||
|
<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="ManageCasesDialog.orgLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="caseNumberLabel">
|
||||||
|
<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="ManageCasesDialog.caseNumberLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="examinerEmailLabel">
|
||||||
|
<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="ManageCasesDialog.examinerEmailLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="examinerNameLabel">
|
||||||
|
<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="ManageCasesDialog.examinerNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="examinerPhoneLabel">
|
||||||
|
<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="ManageCasesDialog.examinerPhoneLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="orgValueLabel">
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="caseNumberValueLabel">
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="examinerNameValueLabel">
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="examinerEmailValueLabel">
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="examinerPhoneValueLabel">
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JButton" name="closeButton">
|
||||||
|
<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="ManageCasesDialog.closeButton.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="[65, 23]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[65, 23]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[65, 23]"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<Events>
|
||||||
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="closeButtonActionPerformed"/>
|
||||||
|
</Events>
|
||||||
|
</Component>
|
||||||
|
</SubComponents>
|
||||||
|
</Container>
|
||||||
|
<Container class="javax.swing.JPanel" name="casesPanel">
|
||||||
|
<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>
|
||||||
|
|
||||||
|
<Layout>
|
||||||
|
<DimensionLayout dim="0">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Group type="102" alignment="0" attributes="0">
|
||||||
|
<Component id="casesScrollPane" pref="379" max="32767" attributes="0"/>
|
||||||
|
<EmptySpace min="-2" 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">
|
||||||
|
<Component id="casesScrollPane" pref="361" max="32767" attributes="0"/>
|
||||||
|
<EmptySpace min="-2" pref="40" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
</Layout>
|
||||||
|
<SubComponents>
|
||||||
|
<Container class="javax.swing.JScrollPane" name="casesScrollPane">
|
||||||
|
<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.JTable" name="casesTable">
|
||||||
|
<Properties>
|
||||||
|
<Property name="autoCreateRowSorter" type="boolean" value="true"/>
|
||||||
|
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||||
|
<Connection code="casesTableModel" type="code"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor">
|
||||||
|
<JTableSelectionModel selectionMode="0"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
</SubComponents>
|
||||||
|
</Container>
|
||||||
|
</SubComponents>
|
||||||
|
</Container>
|
||||||
|
</SubComponents>
|
||||||
|
</Container>
|
||||||
|
</SubComponents>
|
||||||
|
</Form>
|
@ -0,0 +1,353 @@
|
|||||||
|
/*
|
||||||
|
* Central Repository
|
||||||
|
*
|
||||||
|
* Copyright 2018 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.centralrepository.optionspanel;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import javax.swing.event.ListSelectionEvent;
|
||||||
|
import javax.swing.event.ListSelectionListener;
|
||||||
|
import org.openide.windows.WindowManager;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationDataSource;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.openide.util.NbBundle.Messages;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A dialog which displays cases existing in the central repository and the
|
||||||
|
* central repo information associated with them.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
final class ManageCasesDialog extends javax.swing.JDialog {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private final CasesTableModel casesTableModel = new CasesTableModel();
|
||||||
|
private final DataSourcesTableModel dataSourcesTableModel = new DataSourcesTableModel();
|
||||||
|
private final static Logger logger = Logger.getLogger(ManageCasesDialog.class.getName());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new form ManageCasesDialog
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
|
@Messages({"ManageCasesDialog.title.text=Manage Cases"})
|
||||||
|
private ManageCasesDialog() {
|
||||||
|
super(WindowManager.getDefault().getMainWindow(), Bundle.ManageCasesDialog_title_text(),
|
||||||
|
true);
|
||||||
|
initComponents();
|
||||||
|
try {
|
||||||
|
EamDb dbManager = EamDb.getInstance();
|
||||||
|
Map<Integer, List<CorrelationDataSource>> dataSourcesByCaseId = new HashMap<>();
|
||||||
|
for (CorrelationDataSource dataSource : dbManager.getDataSources()) {
|
||||||
|
int caseID = dataSource.getCaseID();
|
||||||
|
List<CorrelationDataSource> dataSourceNames = dataSourcesByCaseId.getOrDefault(caseID, new ArrayList<>());
|
||||||
|
dataSourceNames.add(dataSource);
|
||||||
|
dataSourcesByCaseId.put(caseID, dataSourceNames);
|
||||||
|
}
|
||||||
|
for (CorrelationCase eamCase : dbManager.getCases()) {
|
||||||
|
casesTableModel.addEamCase(eamCase, dataSourcesByCaseId.getOrDefault(eamCase.getID(), new ArrayList<>()));
|
||||||
|
}
|
||||||
|
} catch (EamDbException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Error getting list of cases from database.", ex); // NON-NLS
|
||||||
|
}
|
||||||
|
|
||||||
|
casesTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
|
||||||
|
@Override
|
||||||
|
public void valueChanged(ListSelectionEvent e) {
|
||||||
|
if (!e.getValueIsAdjusting()) {
|
||||||
|
updateSelection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
//sort on first column by default
|
||||||
|
casesTable.getRowSorter().toggleSortOrder(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create and display the Manage Cases dialog for the currently enabled
|
||||||
|
* central repository.
|
||||||
|
*/
|
||||||
|
static void displayManageCasesDialog() {
|
||||||
|
ManageCasesDialog caseInfoDialog = new ManageCasesDialog();
|
||||||
|
caseInfoDialog.setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
|
||||||
|
caseInfoDialog.setVisible(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
|
||||||
|
* regenerated by the Form Editor.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||||
|
private void initComponents() {
|
||||||
|
|
||||||
|
casesSplitPane = new javax.swing.JSplitPane();
|
||||||
|
caseInfoPanel = new javax.swing.JPanel();
|
||||||
|
dataSourcesScrollPane = new javax.swing.JScrollPane();
|
||||||
|
dataSourcesTable = new javax.swing.JTable();
|
||||||
|
notesScrollPane = new javax.swing.JScrollPane();
|
||||||
|
notesTextArea = new javax.swing.JTextArea();
|
||||||
|
caseInfoLabel = new javax.swing.JLabel();
|
||||||
|
dataSourcesLabel = new javax.swing.JLabel();
|
||||||
|
notesLabel = new javax.swing.JLabel();
|
||||||
|
orgLabel = new javax.swing.JLabel();
|
||||||
|
caseNumberLabel = new javax.swing.JLabel();
|
||||||
|
examinerEmailLabel = new javax.swing.JLabel();
|
||||||
|
examinerNameLabel = new javax.swing.JLabel();
|
||||||
|
examinerPhoneLabel = new javax.swing.JLabel();
|
||||||
|
orgValueLabel = new javax.swing.JLabel();
|
||||||
|
caseNumberValueLabel = new javax.swing.JLabel();
|
||||||
|
examinerNameValueLabel = new javax.swing.JLabel();
|
||||||
|
examinerEmailValueLabel = new javax.swing.JLabel();
|
||||||
|
examinerPhoneValueLabel = new javax.swing.JLabel();
|
||||||
|
closeButton = new javax.swing.JButton();
|
||||||
|
casesPanel = new javax.swing.JPanel();
|
||||||
|
casesScrollPane = new javax.swing.JScrollPane();
|
||||||
|
casesTable = new javax.swing.JTable();
|
||||||
|
|
||||||
|
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
|
||||||
|
setMinimumSize(new java.awt.Dimension(400, 400));
|
||||||
|
|
||||||
|
casesSplitPane.setDividerLocation(380);
|
||||||
|
|
||||||
|
dataSourcesTable.setAutoCreateRowSorter(true);
|
||||||
|
dataSourcesTable.setModel(dataSourcesTableModel);
|
||||||
|
dataSourcesTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
|
||||||
|
dataSourcesScrollPane.setViewportView(dataSourcesTable);
|
||||||
|
|
||||||
|
notesScrollPane.setBorder(null);
|
||||||
|
|
||||||
|
notesTextArea.setEditable(false);
|
||||||
|
notesTextArea.setBackground(new java.awt.Color(240, 240, 240));
|
||||||
|
notesTextArea.setColumns(20);
|
||||||
|
notesTextArea.setFont(new java.awt.Font("Tahoma", 0, 11)); // NOI18N
|
||||||
|
notesTextArea.setLineWrap(true);
|
||||||
|
notesTextArea.setRows(3);
|
||||||
|
notesTextArea.setWrapStyleWord(true);
|
||||||
|
notesTextArea.setBorder(null);
|
||||||
|
notesScrollPane.setViewportView(notesTextArea);
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(caseInfoLabel, org.openide.util.NbBundle.getMessage(ManageCasesDialog.class, "ManageCasesDialog.caseInfoLabel.text")); // NOI18N
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(dataSourcesLabel, org.openide.util.NbBundle.getMessage(ManageCasesDialog.class, "ManageCasesDialog.dataSourcesLabel.text")); // NOI18N
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(notesLabel, org.openide.util.NbBundle.getMessage(ManageCasesDialog.class, "ManageCasesDialog.notesLabel.text")); // NOI18N
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(orgLabel, org.openide.util.NbBundle.getMessage(ManageCasesDialog.class, "ManageCasesDialog.orgLabel.text")); // NOI18N
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(caseNumberLabel, org.openide.util.NbBundle.getMessage(ManageCasesDialog.class, "ManageCasesDialog.caseNumberLabel.text")); // NOI18N
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(examinerEmailLabel, org.openide.util.NbBundle.getMessage(ManageCasesDialog.class, "ManageCasesDialog.examinerEmailLabel.text")); // NOI18N
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(examinerNameLabel, org.openide.util.NbBundle.getMessage(ManageCasesDialog.class, "ManageCasesDialog.examinerNameLabel.text")); // NOI18N
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(examinerPhoneLabel, org.openide.util.NbBundle.getMessage(ManageCasesDialog.class, "ManageCasesDialog.examinerPhoneLabel.text")); // NOI18N
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(closeButton, org.openide.util.NbBundle.getMessage(ManageCasesDialog.class, "ManageCasesDialog.closeButton.text")); // NOI18N
|
||||||
|
closeButton.setMaximumSize(new java.awt.Dimension(65, 23));
|
||||||
|
closeButton.setMinimumSize(new java.awt.Dimension(65, 23));
|
||||||
|
closeButton.setPreferredSize(new java.awt.Dimension(65, 23));
|
||||||
|
closeButton.addActionListener(new java.awt.event.ActionListener() {
|
||||||
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
|
closeButtonActionPerformed(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
javax.swing.GroupLayout caseInfoPanelLayout = new javax.swing.GroupLayout(caseInfoPanel);
|
||||||
|
caseInfoPanel.setLayout(caseInfoPanelLayout);
|
||||||
|
caseInfoPanelLayout.setHorizontalGroup(
|
||||||
|
caseInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(caseInfoPanelLayout.createSequentialGroup()
|
||||||
|
.addContainerGap()
|
||||||
|
.addGroup(caseInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(caseInfoPanelLayout.createSequentialGroup()
|
||||||
|
.addGap(10, 10, 10)
|
||||||
|
.addComponent(dataSourcesScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE))
|
||||||
|
.addGroup(caseInfoPanelLayout.createSequentialGroup()
|
||||||
|
.addGap(6, 6, 6)
|
||||||
|
.addGroup(caseInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(caseInfoPanelLayout.createSequentialGroup()
|
||||||
|
.addGroup(caseInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||||
|
.addComponent(orgLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 88, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
|
.addComponent(caseNumberLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 88, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
|
.addComponent(examinerNameLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 88, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
|
.addComponent(examinerEmailLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 88, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
|
.addComponent(examinerPhoneLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 88, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||||
|
.addGroup(caseInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(caseInfoPanelLayout.createSequentialGroup()
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
|
.addGroup(caseInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addComponent(caseNumberValueLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
|
.addComponent(orgValueLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
|
||||||
|
.addGroup(caseInfoPanelLayout.createSequentialGroup()
|
||||||
|
.addGap(6, 6, 6)
|
||||||
|
.addGroup(caseInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addComponent(examinerNameValueLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
|
.addComponent(examinerEmailValueLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
|
.addComponent(examinerPhoneValueLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))))
|
||||||
|
.addComponent(notesLabel)
|
||||||
|
.addGroup(caseInfoPanelLayout.createSequentialGroup()
|
||||||
|
.addGap(10, 10, 10)
|
||||||
|
.addComponent(notesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 428, Short.MAX_VALUE))))
|
||||||
|
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, caseInfoPanelLayout.createSequentialGroup()
|
||||||
|
.addGap(0, 0, Short.MAX_VALUE)
|
||||||
|
.addComponent(closeButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||||
|
.addGroup(caseInfoPanelLayout.createSequentialGroup()
|
||||||
|
.addGroup(caseInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addComponent(caseInfoLabel)
|
||||||
|
.addComponent(dataSourcesLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 77, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||||
|
.addGap(0, 0, Short.MAX_VALUE)))
|
||||||
|
.addContainerGap())
|
||||||
|
);
|
||||||
|
caseInfoPanelLayout.setVerticalGroup(
|
||||||
|
caseInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, caseInfoPanelLayout.createSequentialGroup()
|
||||||
|
.addContainerGap()
|
||||||
|
.addComponent(caseInfoLabel)
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
|
.addGroup(caseInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||||
|
.addGroup(caseInfoPanelLayout.createSequentialGroup()
|
||||||
|
.addGroup(caseInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(caseInfoPanelLayout.createSequentialGroup()
|
||||||
|
.addComponent(orgLabel)
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
|
.addGroup(caseInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||||
|
.addComponent(caseNumberLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
|
.addComponent(caseNumberValueLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
|
.addGroup(caseInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||||
|
.addComponent(examinerNameLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
|
.addComponent(examinerNameValueLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
|
||||||
|
.addComponent(orgValueLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
|
.addComponent(examinerEmailLabel))
|
||||||
|
.addComponent(examinerEmailValueLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
|
.addGroup(caseInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addComponent(examinerPhoneLabel)
|
||||||
|
.addComponent(examinerPhoneValueLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
|
.addComponent(notesLabel)
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
|
.addComponent(notesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 55, Short.MAX_VALUE)
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
|
.addComponent(dataSourcesLabel)
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
|
.addComponent(dataSourcesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 129, Short.MAX_VALUE)
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
|
.addComponent(closeButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
|
.addContainerGap())
|
||||||
|
);
|
||||||
|
|
||||||
|
casesSplitPane.setRightComponent(caseInfoPanel);
|
||||||
|
|
||||||
|
casesTable.setAutoCreateRowSorter(true);
|
||||||
|
casesTable.setModel(casesTableModel);
|
||||||
|
casesTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
|
||||||
|
casesScrollPane.setViewportView(casesTable);
|
||||||
|
|
||||||
|
javax.swing.GroupLayout casesPanelLayout = new javax.swing.GroupLayout(casesPanel);
|
||||||
|
casesPanel.setLayout(casesPanelLayout);
|
||||||
|
casesPanelLayout.setHorizontalGroup(
|
||||||
|
casesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(casesPanelLayout.createSequentialGroup()
|
||||||
|
.addComponent(casesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 379, Short.MAX_VALUE)
|
||||||
|
.addGap(0, 0, 0))
|
||||||
|
);
|
||||||
|
casesPanelLayout.setVerticalGroup(
|
||||||
|
casesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(casesPanelLayout.createSequentialGroup()
|
||||||
|
.addComponent(casesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 361, Short.MAX_VALUE)
|
||||||
|
.addGap(40, 40, 40))
|
||||||
|
);
|
||||||
|
|
||||||
|
casesSplitPane.setLeftComponent(casesPanel);
|
||||||
|
|
||||||
|
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
|
||||||
|
getContentPane().setLayout(layout);
|
||||||
|
layout.setHorizontalGroup(
|
||||||
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addComponent(casesSplitPane, javax.swing.GroupLayout.Alignment.TRAILING)
|
||||||
|
);
|
||||||
|
layout.setVerticalGroup(
|
||||||
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addComponent(casesSplitPane)
|
||||||
|
);
|
||||||
|
|
||||||
|
pack();
|
||||||
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
|
private void closeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeButtonActionPerformed
|
||||||
|
this.dispose();
|
||||||
|
}//GEN-LAST:event_closeButtonActionPerformed
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the information displayed to reflect the currently selected case.
|
||||||
|
*/
|
||||||
|
private void updateSelection() {
|
||||||
|
dataSourcesTableModel.clearTable();
|
||||||
|
if (casesTable.getSelectedRow() >= 0 && casesTable.getSelectedRow() < casesTable.getRowCount()) {
|
||||||
|
CaseDataSourcesWrapper caseWrapper = casesTableModel.getEamCase(casesTable.convertRowIndexToModel(casesTable.getSelectedRow()));
|
||||||
|
orgValueLabel.setText(caseWrapper.getOrganizationName());
|
||||||
|
caseNumberValueLabel.setText(caseWrapper.getCaseNumber());
|
||||||
|
examinerNameValueLabel.setText(caseWrapper.getExaminerName());
|
||||||
|
examinerPhoneValueLabel.setText(caseWrapper.getExaminerPhone());
|
||||||
|
examinerEmailValueLabel.setText(caseWrapper.getExaminerEmail());
|
||||||
|
notesTextArea.setText(caseWrapper.getNotes());
|
||||||
|
dataSourcesTableModel.addDataSources(caseWrapper.getDataSources());
|
||||||
|
} else {
|
||||||
|
orgValueLabel.setText("");
|
||||||
|
caseNumberValueLabel.setText("");
|
||||||
|
examinerNameValueLabel.setText("");
|
||||||
|
examinerPhoneValueLabel.setText("");
|
||||||
|
examinerEmailValueLabel.setText("");
|
||||||
|
notesTextArea.setText("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
|
private javax.swing.JLabel caseInfoLabel;
|
||||||
|
private javax.swing.JPanel caseInfoPanel;
|
||||||
|
private javax.swing.JLabel caseNumberLabel;
|
||||||
|
private javax.swing.JLabel caseNumberValueLabel;
|
||||||
|
private javax.swing.JPanel casesPanel;
|
||||||
|
private javax.swing.JScrollPane casesScrollPane;
|
||||||
|
private javax.swing.JSplitPane casesSplitPane;
|
||||||
|
private javax.swing.JTable casesTable;
|
||||||
|
private javax.swing.JButton closeButton;
|
||||||
|
private javax.swing.JLabel dataSourcesLabel;
|
||||||
|
private javax.swing.JScrollPane dataSourcesScrollPane;
|
||||||
|
private javax.swing.JTable dataSourcesTable;
|
||||||
|
private javax.swing.JLabel examinerEmailLabel;
|
||||||
|
private javax.swing.JLabel examinerEmailValueLabel;
|
||||||
|
private javax.swing.JLabel examinerNameLabel;
|
||||||
|
private javax.swing.JLabel examinerNameValueLabel;
|
||||||
|
private javax.swing.JLabel examinerPhoneLabel;
|
||||||
|
private javax.swing.JLabel examinerPhoneValueLabel;
|
||||||
|
private javax.swing.JLabel notesLabel;
|
||||||
|
private javax.swing.JScrollPane notesScrollPane;
|
||||||
|
private javax.swing.JTextArea notesTextArea;
|
||||||
|
private javax.swing.JLabel orgLabel;
|
||||||
|
private javax.swing.JLabel orgValueLabel;
|
||||||
|
// End of variables declaration//GEN-END:variables
|
||||||
|
}
|
@ -1,169 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
|
||||||
|
|
||||||
<Form version="1.6" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
|
|
||||||
<Properties>
|
|
||||||
<Property name="title" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
|
||||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="ShowCasesDialog.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
|
||||||
</Property>
|
|
||||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
|
||||||
<Dimension value="[545, 415]"/>
|
|
||||||
</Property>
|
|
||||||
</Properties>
|
|
||||||
<SyntheticProperties>
|
|
||||||
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
|
|
||||||
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
|
|
||||||
</SyntheticProperties>
|
|
||||||
<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="6" max="-2" attributes="0"/>
|
|
||||||
<Component id="showCasesPanel" pref="1188" max="32767" attributes="0"/>
|
|
||||||
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
|
|
||||||
</Group>
|
|
||||||
<Group type="102" alignment="1" attributes="0">
|
|
||||||
<EmptySpace max="32767" attributes="0"/>
|
|
||||||
<Component id="closeButton" min="-2" max="-2" attributes="0"/>
|
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
|
||||||
</Group>
|
|
||||||
</Group>
|
|
||||||
</DimensionLayout>
|
|
||||||
<DimensionLayout dim="1">
|
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
|
||||||
<Group type="102" attributes="0">
|
|
||||||
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
|
|
||||||
<Component id="showCasesPanel" pref="473" max="32767" attributes="0"/>
|
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
|
||||||
<Component id="closeButton" min="-2" max="-2" attributes="0"/>
|
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
|
||||||
</Group>
|
|
||||||
</Group>
|
|
||||||
</DimensionLayout>
|
|
||||||
</Layout>
|
|
||||||
<SubComponents>
|
|
||||||
<Container class="javax.swing.JPanel" name="showCasesPanel">
|
|
||||||
<Properties>
|
|
||||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
|
||||||
<Dimension value="[527, 407]"/>
|
|
||||||
</Property>
|
|
||||||
</Properties>
|
|
||||||
|
|
||||||
<Layout>
|
|
||||||
<DimensionLayout dim="0">
|
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
|
||||||
<EmptySpace min="0" pref="1188" max="32767" attributes="0"/>
|
|
||||||
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
|
||||||
<Component id="showCasesScrollPane" alignment="0" pref="527" max="32767" attributes="0"/>
|
|
||||||
</Group>
|
|
||||||
</Group>
|
|
||||||
</DimensionLayout>
|
|
||||||
<DimensionLayout dim="1">
|
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
|
||||||
<EmptySpace min="0" pref="473" max="32767" attributes="0"/>
|
|
||||||
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
|
||||||
<Component id="showCasesScrollPane" alignment="0" pref="407" max="32767" attributes="0"/>
|
|
||||||
</Group>
|
|
||||||
</Group>
|
|
||||||
</DimensionLayout>
|
|
||||||
</Layout>
|
|
||||||
<SubComponents>
|
|
||||||
<Container class="javax.swing.JScrollPane" name="showCasesScrollPane">
|
|
||||||
<Properties>
|
|
||||||
<Property name="verticalScrollBarPolicy" type="int" value="21"/>
|
|
||||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
|
||||||
<Dimension value="[535, 415]"/>
|
|
||||||
</Property>
|
|
||||||
</Properties>
|
|
||||||
|
|
||||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
|
||||||
<SubComponents>
|
|
||||||
<Container class="javax.swing.JPanel" name="outCasesPane">
|
|
||||||
|
|
||||||
<Layout>
|
|
||||||
<DimensionLayout dim="0">
|
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
|
||||||
<EmptySpace min="0" pref="1423" max="32767" attributes="0"/>
|
|
||||||
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
|
||||||
<Component id="innerCaseScrollPane" alignment="0" pref="1423" max="32767" attributes="0"/>
|
|
||||||
</Group>
|
|
||||||
</Group>
|
|
||||||
</DimensionLayout>
|
|
||||||
<DimensionLayout dim="1">
|
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
|
||||||
<EmptySpace min="0" pref="500" max="32767" attributes="0"/>
|
|
||||||
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
|
||||||
<Component id="innerCaseScrollPane" alignment="0" pref="500" max="32767" attributes="0"/>
|
|
||||||
</Group>
|
|
||||||
</Group>
|
|
||||||
</DimensionLayout>
|
|
||||||
</Layout>
|
|
||||||
<SubComponents>
|
|
||||||
<Container class="javax.swing.JScrollPane" name="innerCaseScrollPane">
|
|
||||||
<Properties>
|
|
||||||
<Property name="horizontalScrollBarPolicy" type="int" value="31"/>
|
|
||||||
</Properties>
|
|
||||||
|
|
||||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
|
||||||
<SubComponents>
|
|
||||||
<Component class="javax.swing.JTable" name="caseDetailsTable">
|
|
||||||
<Properties>
|
|
||||||
<Property name="autoCreateRowSorter" type="boolean" value="true"/>
|
|
||||||
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
|
||||||
<Connection code="tableModel" type="code"/>
|
|
||||||
</Property>
|
|
||||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
|
||||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="ShowCasesDialog.caseDetailsTable.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
|
||||||
</Property>
|
|
||||||
<Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor">
|
|
||||||
<JTableSelectionModel selectionMode="1"/>
|
|
||||||
</Property>
|
|
||||||
<Property name="tableHeader" type="javax.swing.table.JTableHeader" editor="org.netbeans.modules.form.editors2.JTableHeaderEditor">
|
|
||||||
<TableHeader reorderingAllowed="false" resizingAllowed="true"/>
|
|
||||||
</Property>
|
|
||||||
</Properties>
|
|
||||||
<AccessibilityProperties>
|
|
||||||
<Property name="AccessibleContext.accessibleDescription" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
|
||||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="ShowCasesDialog.caseDetailsTable.AccessibleContext.accessibleDescription" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
|
||||||
</Property>
|
|
||||||
</AccessibilityProperties>
|
|
||||||
</Component>
|
|
||||||
</SubComponents>
|
|
||||||
</Container>
|
|
||||||
</SubComponents>
|
|
||||||
</Container>
|
|
||||||
</SubComponents>
|
|
||||||
</Container>
|
|
||||||
</SubComponents>
|
|
||||||
</Container>
|
|
||||||
<Component class="javax.swing.JButton" name="closeButton">
|
|
||||||
<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="ShowCasesDialog.closeButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
|
||||||
</Property>
|
|
||||||
<Property name="actionCommand" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
|
||||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="ShowCasesDialog.closeButton.actionCommand" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
|
||||||
</Property>
|
|
||||||
</Properties>
|
|
||||||
<AccessibilityProperties>
|
|
||||||
<Property name="AccessibleContext.accessibleName" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
|
||||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="ShowCasesDialog.closeButton.AccessibleContext.accessibleName" 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="closeButtonActionPerformed"/>
|
|
||||||
</Events>
|
|
||||||
</Component>
|
|
||||||
</SubComponents>
|
|
||||||
</Form>
|
|
@ -1,190 +0,0 @@
|
|||||||
/*
|
|
||||||
* Central Repository
|
|
||||||
*
|
|
||||||
* Copyright 2015-2018 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.centralrepository.optionspanel;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import javax.swing.JDialog;
|
|
||||||
import javax.swing.JFrame;
|
|
||||||
import org.openide.util.NbBundle.Messages;
|
|
||||||
import org.openide.windows.WindowManager;
|
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase;
|
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dialog to display table of CorrelationCase information from the CR tab of options.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
|
||||||
final class ShowCasesDialog extends JDialog {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
private final static Logger logger = Logger.getLogger(ShowCasesDialog.class.getName());
|
|
||||||
|
|
||||||
private final ShowCasesTableModel tableModel;
|
|
||||||
@Messages({"ShowCasesDialog.title_text=All Cases Details"})
|
|
||||||
/**
|
|
||||||
* Creates new form ShowCases Panel
|
|
||||||
*/
|
|
||||||
ShowCasesDialog() {
|
|
||||||
super((JFrame) WindowManager.getDefault().getMainWindow(),
|
|
||||||
Bundle.ShowCasesDialog_title_text(),
|
|
||||||
true);
|
|
||||||
tableModel = new ShowCasesTableModel();
|
|
||||||
initComponents();
|
|
||||||
try {
|
|
||||||
EamDb dbManager = EamDb.getInstance();
|
|
||||||
List<CorrelationCase> eamCases = dbManager.getCases();
|
|
||||||
for(CorrelationCase eamCase : eamCases) {
|
|
||||||
tableModel.addEamCase(eamCase);
|
|
||||||
}
|
|
||||||
} catch (EamDbException ex) {
|
|
||||||
logger.log(Level.SEVERE, "Error getting list of cases from database.", ex); // NON-NLS
|
|
||||||
}
|
|
||||||
display();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void display() {
|
|
||||||
this.setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
|
|
||||||
setVisible(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
|
|
||||||
* regenerated by the Form Editor.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
|
||||||
private void initComponents() {
|
|
||||||
|
|
||||||
showCasesPanel = new javax.swing.JPanel();
|
|
||||||
showCasesScrollPane = new javax.swing.JScrollPane();
|
|
||||||
outCasesPane = new javax.swing.JPanel();
|
|
||||||
innerCaseScrollPane = new javax.swing.JScrollPane();
|
|
||||||
caseDetailsTable = new javax.swing.JTable();
|
|
||||||
closeButton = new javax.swing.JButton();
|
|
||||||
|
|
||||||
setTitle(org.openide.util.NbBundle.getMessage(ShowCasesDialog.class, "ShowCasesDialog.title")); // NOI18N
|
|
||||||
setMinimumSize(new java.awt.Dimension(545, 415));
|
|
||||||
|
|
||||||
showCasesPanel.setPreferredSize(new java.awt.Dimension(527, 407));
|
|
||||||
|
|
||||||
showCasesScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
|
|
||||||
showCasesScrollPane.setPreferredSize(new java.awt.Dimension(535, 415));
|
|
||||||
|
|
||||||
innerCaseScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
|
||||||
|
|
||||||
caseDetailsTable.setAutoCreateRowSorter(true);
|
|
||||||
caseDetailsTable.setModel(tableModel);
|
|
||||||
caseDetailsTable.setToolTipText(org.openide.util.NbBundle.getMessage(ShowCasesDialog.class, "ShowCasesDialog.caseDetailsTable.toolTipText")); // NOI18N
|
|
||||||
caseDetailsTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_INTERVAL_SELECTION);
|
|
||||||
caseDetailsTable.getTableHeader().setReorderingAllowed(false);
|
|
||||||
innerCaseScrollPane.setViewportView(caseDetailsTable);
|
|
||||||
caseDetailsTable.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(ShowCasesDialog.class, "ShowCasesDialog.caseDetailsTable.AccessibleContext.accessibleDescription")); // NOI18N
|
|
||||||
|
|
||||||
javax.swing.GroupLayout outCasesPaneLayout = new javax.swing.GroupLayout(outCasesPane);
|
|
||||||
outCasesPane.setLayout(outCasesPaneLayout);
|
|
||||||
outCasesPaneLayout.setHorizontalGroup(
|
|
||||||
outCasesPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
|
||||||
.addGap(0, 1423, Short.MAX_VALUE)
|
|
||||||
.addGroup(outCasesPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
|
||||||
.addComponent(innerCaseScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 1423, Short.MAX_VALUE))
|
|
||||||
);
|
|
||||||
outCasesPaneLayout.setVerticalGroup(
|
|
||||||
outCasesPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
|
||||||
.addGap(0, 500, Short.MAX_VALUE)
|
|
||||||
.addGroup(outCasesPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
|
||||||
.addComponent(innerCaseScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 500, Short.MAX_VALUE))
|
|
||||||
);
|
|
||||||
|
|
||||||
showCasesScrollPane.setViewportView(outCasesPane);
|
|
||||||
|
|
||||||
javax.swing.GroupLayout showCasesPanelLayout = new javax.swing.GroupLayout(showCasesPanel);
|
|
||||||
showCasesPanel.setLayout(showCasesPanelLayout);
|
|
||||||
showCasesPanelLayout.setHorizontalGroup(
|
|
||||||
showCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
|
||||||
.addGap(0, 1188, Short.MAX_VALUE)
|
|
||||||
.addGroup(showCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
|
||||||
.addComponent(showCasesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 527, Short.MAX_VALUE))
|
|
||||||
);
|
|
||||||
showCasesPanelLayout.setVerticalGroup(
|
|
||||||
showCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
|
||||||
.addGap(0, 473, Short.MAX_VALUE)
|
|
||||||
.addGroup(showCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
|
||||||
.addComponent(showCasesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 407, Short.MAX_VALUE))
|
|
||||||
);
|
|
||||||
|
|
||||||
org.openide.awt.Mnemonics.setLocalizedText(closeButton, org.openide.util.NbBundle.getMessage(ShowCasesDialog.class, "ShowCasesDialog.closeButton.text")); // NOI18N
|
|
||||||
closeButton.setActionCommand(org.openide.util.NbBundle.getMessage(ShowCasesDialog.class, "ShowCasesDialog.closeButton.actionCommand")); // NOI18N
|
|
||||||
closeButton.addActionListener(new java.awt.event.ActionListener() {
|
|
||||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
|
||||||
closeButtonActionPerformed(evt);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
|
|
||||||
getContentPane().setLayout(layout);
|
|
||||||
layout.setHorizontalGroup(
|
|
||||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
|
||||||
.addGroup(layout.createSequentialGroup()
|
|
||||||
.addGap(6, 6, 6)
|
|
||||||
.addComponent(showCasesPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 1188, Short.MAX_VALUE)
|
|
||||||
.addGap(6, 6, 6))
|
|
||||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
|
||||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
|
||||||
.addComponent(closeButton)
|
|
||||||
.addContainerGap())
|
|
||||||
);
|
|
||||||
layout.setVerticalGroup(
|
|
||||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
|
||||||
.addGroup(layout.createSequentialGroup()
|
|
||||||
.addGap(6, 6, 6)
|
|
||||||
.addComponent(showCasesPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 473, Short.MAX_VALUE)
|
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
|
||||||
.addComponent(closeButton)
|
|
||||||
.addContainerGap())
|
|
||||||
);
|
|
||||||
|
|
||||||
closeButton.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(ShowCasesDialog.class, "ShowCasesDialog.closeButton.AccessibleContext.accessibleName")); // NOI18N
|
|
||||||
|
|
||||||
pack();
|
|
||||||
}// </editor-fold>//GEN-END:initComponents
|
|
||||||
|
|
||||||
private void closeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeButtonActionPerformed
|
|
||||||
dispose();
|
|
||||||
}//GEN-LAST:event_closeButtonActionPerformed
|
|
||||||
|
|
||||||
|
|
||||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
|
||||||
private javax.swing.JTable caseDetailsTable;
|
|
||||||
private javax.swing.JButton closeButton;
|
|
||||||
private javax.swing.JScrollPane innerCaseScrollPane;
|
|
||||||
private javax.swing.JPanel outCasesPane;
|
|
||||||
private javax.swing.JPanel showCasesPanel;
|
|
||||||
private javax.swing.JScrollPane showCasesScrollPane;
|
|
||||||
// End of variables declaration//GEN-END:variables
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,187 +0,0 @@
|
|||||||
/*
|
|
||||||
* Central Repository
|
|
||||||
*
|
|
||||||
* Copyright 2018 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.centralrepository.optionspanel;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import javax.swing.table.AbstractTableModel;
|
|
||||||
import org.openide.util.NbBundle.Messages;
|
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Model for cells to display correlation case information
|
|
||||||
*/
|
|
||||||
class ShowCasesTableModel extends AbstractTableModel {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
@Messages({"ShowCasesTableModel.case=Case Name",
|
|
||||||
"ShowCasesTableModel.creationDate=Creation Date",
|
|
||||||
"ShowCasesTableModel.caseNumber=Case Number",
|
|
||||||
"ShowCasesTableModel.examinerName=Examiner Name",
|
|
||||||
"ShowCasesTableModel.examinerEmail=Examiner Email",
|
|
||||||
"ShowCasesTableModel.examinerPhone=Examiner Phone",
|
|
||||||
"ShowCasesTableModel.notes=Notes",
|
|
||||||
"ShowCasesTableModel.noData=No Cases"})
|
|
||||||
/**
|
|
||||||
* Enum which lists columns of interest from CorrelationCase.
|
|
||||||
*/
|
|
||||||
enum TableColumns {
|
|
||||||
// Ordering here determines displayed column order in Content Viewer.
|
|
||||||
// If order is changed, update the CellRenderer to ensure correct row coloring.
|
|
||||||
CASE_NAME(Bundle.ShowCasesTableModel_case(), 200),
|
|
||||||
CREATION_DATE(Bundle.ShowCasesTableModel_creationDate(), 150),
|
|
||||||
CASE_NUMBER(Bundle.ShowCasesTableModel_caseNumber(), 100),
|
|
||||||
EXAMINER_NAME(Bundle.ShowCasesTableModel_examinerName(), 200),
|
|
||||||
EXAMINER_EMAIL(Bundle.ShowCasesTableModel_examinerEmail(), 100),
|
|
||||||
EXAMINER_PHONE(Bundle.ShowCasesTableModel_examinerPhone(), 100),
|
|
||||||
NOTES(Bundle.ShowCasesTableModel_notes(), 450);
|
|
||||||
|
|
||||||
private final String columnName;
|
|
||||||
private final int columnWidth;
|
|
||||||
|
|
||||||
TableColumns(String columnName, int columnWidth) {
|
|
||||||
this.columnName = columnName;
|
|
||||||
this.columnWidth = columnWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
String columnName() {
|
|
||||||
return columnName;
|
|
||||||
}
|
|
||||||
|
|
||||||
int columnWidth() {
|
|
||||||
return columnWidth;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* list of Eam Cases from central repository.
|
|
||||||
*/
|
|
||||||
private List<CorrelationCase> eamCases;
|
|
||||||
|
|
||||||
ShowCasesTableModel() {
|
|
||||||
eamCases = new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getColumnCount() {
|
|
||||||
return TableColumns.values().length;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the preferred width that has been configured for this column.
|
|
||||||
*
|
|
||||||
* A value of 0 means that no preferred width has been defined for this
|
|
||||||
* column.
|
|
||||||
*
|
|
||||||
* @param colIdx Column index
|
|
||||||
*
|
|
||||||
* @return preferred column width >= 0
|
|
||||||
*/
|
|
||||||
int getColumnPreferredWidth(int colIdx) {
|
|
||||||
return TableColumns.values()[colIdx].columnWidth();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getRowCount() {
|
|
||||||
return eamCases.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getColumnName(int colIdx) {
|
|
||||||
return TableColumns.values()[colIdx].columnName();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object getValueAt(int rowIdx, int colIdx) {
|
|
||||||
if (eamCases.isEmpty()) {
|
|
||||||
return Bundle.ShowCasesTableModel_noData();
|
|
||||||
}
|
|
||||||
|
|
||||||
return mapValueById(rowIdx, TableColumns.values()[colIdx]);
|
|
||||||
}
|
|
||||||
|
|
||||||
Object getRow(int rowIdx) {
|
|
||||||
return eamCases.get(rowIdx);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Map a rowIdx and colId to the value in that cell.
|
|
||||||
*
|
|
||||||
* @param rowIdx Index of row to search
|
|
||||||
* @param colId ID of column to search
|
|
||||||
*
|
|
||||||
* @return value in the cell
|
|
||||||
*/
|
|
||||||
private Object mapValueById(int rowIdx, TableColumns colId) {
|
|
||||||
CorrelationCase eamCase = eamCases.get(rowIdx);
|
|
||||||
String value = Bundle.ShowCasesTableModel_noData();
|
|
||||||
|
|
||||||
switch (colId) {
|
|
||||||
case CASE_NAME:
|
|
||||||
value = eamCase.getDisplayName();
|
|
||||||
break;
|
|
||||||
case CREATION_DATE:
|
|
||||||
value = eamCase.getCreationDate();
|
|
||||||
break;
|
|
||||||
case CASE_NUMBER:
|
|
||||||
value = eamCase.getCaseNumber();
|
|
||||||
break;
|
|
||||||
case EXAMINER_NAME:
|
|
||||||
value = eamCase.getExaminerName();
|
|
||||||
break;
|
|
||||||
case EXAMINER_EMAIL:
|
|
||||||
value = eamCase.getExaminerEmail();
|
|
||||||
break;
|
|
||||||
case EXAMINER_PHONE:
|
|
||||||
value = eamCase.getExaminerPhone();
|
|
||||||
break;
|
|
||||||
case NOTES:
|
|
||||||
value = eamCase.getNotes();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<String> getColumnClass(int colIdx) {
|
|
||||||
return String.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add one local central repository case to the table.
|
|
||||||
*
|
|
||||||
* @param eamCase central repository case to add to the
|
|
||||||
* table
|
|
||||||
*/
|
|
||||||
void addEamCase(CorrelationCase eamCase) {
|
|
||||||
eamCases.add(eamCase);
|
|
||||||
fireTableDataChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
void clearTable() {
|
|
||||||
eamCases.clear();
|
|
||||||
fireTableDataChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -303,9 +303,8 @@
|
|||||||
<DimensionLayout dim="0">
|
<DimensionLayout dim="0">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Group type="102" attributes="0">
|
<Group type="102" attributes="0">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Component id="dateRangeLabel" min="-2" max="-2" attributes="0"/>
|
<Component id="dateRangeLabel" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
|
||||||
</Group>
|
|
||||||
<Group type="102" attributes="0">
|
<Group type="102" attributes="0">
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
@ -322,6 +321,9 @@
|
|||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
|
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
<DimensionLayout dim="1">
|
<DimensionLayout dim="1">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
@ -124,7 +124,8 @@ final public class FiltersPanel extends JPanel {
|
|||||||
|
|
||||||
updateFilters(true);
|
updateFilters(true);
|
||||||
UserPreferences.addChangeListener(preferenceChangeEvent -> {
|
UserPreferences.addChangeListener(preferenceChangeEvent -> {
|
||||||
if (preferenceChangeEvent.getKey().equals(UserPreferences.DISPLAY_TIMES_IN_LOCAL_TIME)) {
|
if (preferenceChangeEvent.getKey().equals(UserPreferences.DISPLAY_TIMES_IN_LOCAL_TIME) ||
|
||||||
|
preferenceChangeEvent.getKey().equals(UserPreferences.TIME_ZONE_FOR_DISPLAYS)) {
|
||||||
updateTimeZone();
|
updateTimeZone();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -175,7 +176,7 @@ final public class FiltersPanel extends JPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateTimeZone() {
|
private void updateTimeZone() {
|
||||||
dateRangeLabel.setText("Date Range ( " + Utils.getUserPreferredZoneId().toString() + "):");
|
dateRangeLabel.setText("Date Range (" + Utils.getUserPreferredZoneId().toString() + "):");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.communications;
|
|||||||
|
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
import java.time.ZoneOffset;
|
import java.time.ZoneOffset;
|
||||||
|
import java.util.TimeZone;
|
||||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||||
import org.sleuthkit.autopsy.datamodel.accounts.Accounts;
|
import org.sleuthkit.autopsy.datamodel.accounts.Accounts;
|
||||||
import org.sleuthkit.datamodel.Account;
|
import org.sleuthkit.datamodel.Account;
|
||||||
@ -33,7 +34,8 @@ class Utils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static ZoneId getUserPreferredZoneId() {
|
static ZoneId getUserPreferredZoneId() {
|
||||||
ZoneId zone = UserPreferences.displayTimesInLocalTime() ? ZoneOffset.systemDefault() : ZoneOffset.UTC;
|
ZoneId zone = UserPreferences.displayTimesInLocalTime() ?
|
||||||
|
ZoneOffset.systemDefault() : TimeZone.getTimeZone(UserPreferences.getTimeZoneForDisplays()).toZoneId();
|
||||||
return zone;
|
return zone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -424,7 +424,7 @@ class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer {
|
|||||||
|
|
||||||
try (Statement statement = connection.createStatement();
|
try (Statement statement = connection.createStatement();
|
||||||
ResultSet resultSet = statement.executeQuery(
|
ResultSet resultSet = statement.executeQuery(
|
||||||
"SELECT count (*) as count FROM " + "\"" + tableName + "\"")) { //NON-NLS{
|
"SELECT count (*) as count FROM " + "\"" + tableName + "\"")) { //NON-NLS
|
||||||
|
|
||||||
numRows = resultSet.getInt("count");
|
numRows = resultSet.getInt("count");
|
||||||
numEntriesField.setText(numRows + " entries");
|
numEntriesField.setText(numRows + " entries");
|
||||||
@ -442,9 +442,23 @@ class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer {
|
|||||||
} else {
|
} else {
|
||||||
exportCsvButton.setEnabled(false);
|
exportCsvButton.setEnabled(false);
|
||||||
nextPageButton.setEnabled(false);
|
nextPageButton.setEnabled(false);
|
||||||
selectedTableView.setupTable(Collections.emptyList());
|
|
||||||
|
//Execute a dummy SELECT * statement so that the metadata
|
||||||
|
//contains all column names
|
||||||
|
Map<String, Object> columnRow;
|
||||||
|
try (ResultSet metaDataResultSet = statement.executeQuery(
|
||||||
|
"SELECT * FROM " + "\"" + tableName + "\"")) {
|
||||||
|
//Column names are not found in the metadata of the result set
|
||||||
|
//above.
|
||||||
|
ResultSetMetaData metaData = metaDataResultSet.getMetaData();
|
||||||
|
columnRow = new LinkedHashMap<>();
|
||||||
|
for(int i = 1; i < metaData.getColumnCount(); i++){
|
||||||
|
columnRow.put(metaData.getColumnName(i), "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
selectedTableView.setupTable(Collections.singletonList(columnRow));
|
||||||
|
}
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
logger.log(Level.SEVERE, String.format("Failed to load table %s from DB file '%s' (objId=%d)", tableName, sqliteDbFile.getName(), sqliteDbFile.getId()), ex); //NON-NLS
|
logger.log(Level.SEVERE, String.format("Failed to load table %s from DB file '%s' (objId=%d)", tableName, sqliteDbFile.getName(), sqliteDbFile.getId()), ex); //NON-NLS
|
||||||
MessageNotifyUtil.Message.error(Bundle.SQLiteViewer_selectTable_errorText(tableName));
|
MessageNotifyUtil.Message.error(Bundle.SQLiteViewer_selectTable_errorText(tableName));
|
||||||
|
@ -24,6 +24,7 @@ import org.sleuthkit.autopsy.events.MessageServiceConnectionInfo;
|
|||||||
import java.util.prefs.PreferenceChangeListener;
|
import java.util.prefs.PreferenceChangeListener;
|
||||||
import java.util.prefs.Preferences;
|
import java.util.prefs.Preferences;
|
||||||
import org.openide.util.NbPreferences;
|
import org.openide.util.NbPreferences;
|
||||||
|
import org.python.icu.util.TimeZone;
|
||||||
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
|
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
|
||||||
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
||||||
import org.sleuthkit.autopsy.coreutils.TextConverterException;
|
import org.sleuthkit.autopsy.coreutils.TextConverterException;
|
||||||
@ -45,6 +46,7 @@ public final class UserPreferences {
|
|||||||
public static final String HIDE_SLACK_FILES_IN_DATA_SRCS_TREE = "HideSlackFilesInDataSourcesTree"; //NON-NLS
|
public static final String HIDE_SLACK_FILES_IN_DATA_SRCS_TREE = "HideSlackFilesInDataSourcesTree"; //NON-NLS
|
||||||
public static final String HIDE_SLACK_FILES_IN_VIEWS_TREE = "HideSlackFilesInViewsTree"; //NON-NLS
|
public static final String HIDE_SLACK_FILES_IN_VIEWS_TREE = "HideSlackFilesInViewsTree"; //NON-NLS
|
||||||
public static final String DISPLAY_TIMES_IN_LOCAL_TIME = "DisplayTimesInLocalTime"; //NON-NLS
|
public static final String DISPLAY_TIMES_IN_LOCAL_TIME = "DisplayTimesInLocalTime"; //NON-NLS
|
||||||
|
public static final String TIME_ZONE_FOR_DISPLAYS = "TimeZoneForDisplays"; //NON-NLS
|
||||||
public static final String NUMBER_OF_FILE_INGEST_THREADS = "NumberOfFileIngestThreads"; //NON-NLS
|
public static final String NUMBER_OF_FILE_INGEST_THREADS = "NumberOfFileIngestThreads"; //NON-NLS
|
||||||
public static final String IS_MULTI_USER_MODE_ENABLED = "IsMultiUserModeEnabled"; //NON-NLS
|
public static final String IS_MULTI_USER_MODE_ENABLED = "IsMultiUserModeEnabled"; //NON-NLS
|
||||||
public static final String EXTERNAL_DATABASE_HOSTNAME_OR_IP = "ExternalDatabaseHostnameOrIp"; //NON-NLS
|
public static final String EXTERNAL_DATABASE_HOSTNAME_OR_IP = "ExternalDatabaseHostnameOrIp"; //NON-NLS
|
||||||
@ -182,6 +184,14 @@ public final class UserPreferences {
|
|||||||
preferences.putBoolean(DISPLAY_TIMES_IN_LOCAL_TIME, value);
|
preferences.putBoolean(DISPLAY_TIMES_IN_LOCAL_TIME, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getTimeZoneForDisplays() {
|
||||||
|
return preferences.get(TIME_ZONE_FOR_DISPLAYS, TimeZone.GMT_ZONE.getID());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setTimeZoneForDisplays(String timeZone) {
|
||||||
|
preferences.put(TIME_ZONE_FOR_DISPLAYS, timeZone);
|
||||||
|
}
|
||||||
|
|
||||||
public static int numberOfFileIngestThreads() {
|
public static int numberOfFileIngestThreads() {
|
||||||
return preferences.getInt(NUMBER_OF_FILE_INGEST_THREADS, 2);
|
return preferences.getInt(NUMBER_OF_FILE_INGEST_THREADS, 2);
|
||||||
}
|
}
|
||||||
|
@ -180,7 +180,6 @@ ViewPreferencesPanel.useBestViewerRadioButton.text=Change to the most specific f
|
|||||||
ViewPreferencesPanel.keepCurrentViewerRadioButton.toolTipText=For example, stay in Hex view when a JPEG is selected.
|
ViewPreferencesPanel.keepCurrentViewerRadioButton.toolTipText=For example, stay in Hex view when a JPEG is selected.
|
||||||
ViewPreferencesPanel.keepCurrentViewerRadioButton.text=Stay on the same file viewer
|
ViewPreferencesPanel.keepCurrentViewerRadioButton.text=Stay on the same file viewer
|
||||||
ViewPreferencesPanel.useLocalTimeRadioButton.text=Use local time zone
|
ViewPreferencesPanel.useLocalTimeRadioButton.text=Use local time zone
|
||||||
ViewPreferencesPanel.useGMTTimeRadioButton.text=Use GMT
|
|
||||||
ViewPreferencesPanel.dataSourcesHideKnownCheckbox.text=Data Sources area (the directory hierarchy)
|
ViewPreferencesPanel.dataSourcesHideKnownCheckbox.text=Data Sources area (the directory hierarchy)
|
||||||
ViewPreferencesPanel.viewsHideKnownCheckbox.text=Views area
|
ViewPreferencesPanel.viewsHideKnownCheckbox.text=Views area
|
||||||
ViewPreferencesPanel.dataSourcesHideSlackCheckbox.text=Data Sources area (the directory hierarchy)
|
ViewPreferencesPanel.dataSourcesHideSlackCheckbox.text=Data Sources area (the directory hierarchy)
|
||||||
@ -192,3 +191,4 @@ ViewPreferencesPanel.centralRepoLabel.text=Do not use Central Repository for:
|
|||||||
ViewPreferencesPanel.commentsOccurencesColumnsCheckbox.text=C(omments) and O(ccurences) columns to reduce loading times
|
ViewPreferencesPanel.commentsOccurencesColumnsCheckbox.text=C(omments) and O(ccurences) columns to reduce loading times
|
||||||
ViewPreferencesPanel.deletedFilesLimitCheckbox.text=Limit to 10,000
|
ViewPreferencesPanel.deletedFilesLimitCheckbox.text=Limit to 10,000
|
||||||
ViewPreferencesPanel.deletedFilesLimitLabel.text=Limit number of deleted files displayed:
|
ViewPreferencesPanel.deletedFilesLimitLabel.text=Limit number of deleted files displayed:
|
||||||
|
ViewPreferencesPanel.useAnotherTimeRadioButton.text=Use another time zone
|
||||||
|
@ -128,6 +128,5 @@ ViewPreferencesPanel.useBestViewerRadioButton.text=\u6700\u3082\u5c02\u9580\u768
|
|||||||
ViewPreferencesPanel.keepCurrentViewerRadioButton.text=\u305d\u306e\u307e\u307e\u540c\u3058\u30d5\u30a1\u30a4\u30eb\u30d3\u30e5\u30fc\u30a2\u3092\u4f7f\u7528
|
ViewPreferencesPanel.keepCurrentViewerRadioButton.text=\u305d\u306e\u307e\u307e\u540c\u3058\u30d5\u30a1\u30a4\u30eb\u30d3\u30e5\u30fc\u30a2\u3092\u4f7f\u7528
|
||||||
ViewPreferencesPanel.keepCurrentViewerRadioButton.toolTipText=\u4f8b\u3048\u3070\u3001JPEG\u304c\u9078\u629e\u3055\u308c\u305f\u5834\u5408\u306b\u305d\u306e\u307e\u307eHEX\u30d3\u30e5\u30fc\u3092\u4f7f\u7528\u3002
|
ViewPreferencesPanel.keepCurrentViewerRadioButton.toolTipText=\u4f8b\u3048\u3070\u3001JPEG\u304c\u9078\u629e\u3055\u308c\u305f\u5834\u5408\u306b\u305d\u306e\u307e\u307eHEX\u30d3\u30e5\u30fc\u3092\u4f7f\u7528\u3002
|
||||||
ViewPreferencesPanel.useLocalTimeRadioButton.text=\u30ed\u30fc\u30ab\u30eb\u30bf\u30a4\u30e0\u30be\u30fc\u30f3\u3092\u4f7f\u7528
|
ViewPreferencesPanel.useLocalTimeRadioButton.text=\u30ed\u30fc\u30ab\u30eb\u30bf\u30a4\u30e0\u30be\u30fc\u30f3\u3092\u4f7f\u7528
|
||||||
ViewPreferencesPanel.useGMTTimeRadioButton.text=GMT\u3092\u4f7f\u7528
|
|
||||||
ViewPreferencesPanel.dataSourcesHideKnownCheckbox.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u30a8\u30ea\u30a2\uff08\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u968e\u5c64\uff09
|
ViewPreferencesPanel.dataSourcesHideKnownCheckbox.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u30a8\u30ea\u30a2\uff08\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u968e\u5c64\uff09
|
||||||
ViewPreferencesPanel.viewsHideKnownCheckbox.text=\u30d3\u30e5\u30fc\u30a8\u30ea\u30a2
|
ViewPreferencesPanel.viewsHideKnownCheckbox.text=\u30d3\u30e5\u30fc\u30a8\u30ea\u30a2
|
||||||
|
@ -487,7 +487,8 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
|
|||||||
|| (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID())
|
|| (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID())
|
||||||
|| (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID())
|
|| (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID())
|
||||||
|| (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_OBJECT_DETECTED.getTypeID())
|
|| (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_OBJECT_DETECTED.getTypeID())
|
||||||
|| (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_METADATA_EXIF.getTypeID())) {
|
|| (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_METADATA_EXIF.getTypeID())
|
||||||
|
|| (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_EXT_MISMATCH_DETECTED.getTypeID())) {
|
||||||
return 3;
|
return 3;
|
||||||
} else {
|
} else {
|
||||||
return 6;
|
return 6;
|
||||||
|
@ -40,6 +40,7 @@ public final class TextPrompt extends JLabel
|
|||||||
|
|
||||||
public TextPrompt(String text, JTextComponent component, Show show) {
|
public TextPrompt(String text, JTextComponent component, Show show) {
|
||||||
this.component = component;
|
this.component = component;
|
||||||
|
component.removeAll();
|
||||||
setShow(show);
|
setShow(show);
|
||||||
document = component.getDocument();
|
document = component.getDocument();
|
||||||
|
|
||||||
|
@ -31,11 +31,19 @@
|
|||||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||||
<Border info="null"/>
|
<Border info="null"/>
|
||||||
</Property>
|
</Property>
|
||||||
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[625, 452]"/>
|
||||||
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
|
|
||||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||||
<SubComponents>
|
<SubComponents>
|
||||||
<Container class="javax.swing.JPanel" name="viewPreferencesPanel">
|
<Container class="javax.swing.JPanel" name="viewPreferencesPanel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[625, 452]"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
|
||||||
<Layout>
|
<Layout>
|
||||||
<DimensionLayout dim="0">
|
<DimensionLayout dim="0">
|
||||||
@ -87,9 +95,19 @@
|
|||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Component id="commentsOccurencesColumnsCheckbox" min="-2" max="-2" attributes="0"/>
|
<Component id="commentsOccurencesColumnsCheckbox" min="-2" max="-2" attributes="0"/>
|
||||||
<Component id="hideOtherUsersTagsCheckbox" min="-2" max="-2" attributes="0"/>
|
<Component id="hideOtherUsersTagsCheckbox" min="-2" max="-2" attributes="0"/>
|
||||||
<Component id="deletedFilesLimitCheckbox" alignment="0" max="32767" attributes="0"/>
|
<Group type="102" alignment="0" attributes="0">
|
||||||
|
<Component id="deletedFilesLimitCheckbox" max="32767" attributes="0"/>
|
||||||
|
<EmptySpace min="-2" pref="399" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
|
</Group>
|
||||||
|
<Group type="102" attributes="0">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Group type="102" alignment="0" attributes="0">
|
||||||
|
<Component id="centralRepoLabel" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace min="-2" pref="135" max="-2" attributes="0"/>
|
||||||
|
<Component id="jScrollPane1" min="-2" pref="272" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
<Group type="102" attributes="0">
|
<Group type="102" attributes="0">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Group type="102" alignment="0" attributes="0">
|
<Group type="102" alignment="0" attributes="0">
|
||||||
@ -123,23 +141,24 @@
|
|||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Component id="keepCurrentViewerRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
<Component id="keepCurrentViewerRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||||
<Component id="useBestViewerRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
<Component id="useBestViewerRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||||
<Component id="useGMTTimeRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
|
||||||
<Component id="useLocalTimeRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
<Component id="useLocalTimeRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="useAnotherTimeRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
<Component id="selectFileLabel" min="-2" max="-2" attributes="0"/>
|
<Component id="selectFileLabel" min="-2" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
<Component id="hideOtherUsersTagsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
<Component id="hideOtherUsersTagsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||||
<Component id="centralRepoLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
|
||||||
<Component id="deletedFilesLimitLabel" alignment="0" min="-2" pref="215" max="-2" attributes="0"/>
|
<Component id="deletedFilesLimitLabel" alignment="0" min="-2" pref="215" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
<EmptySpace min="0" pref="10" max="32767" attributes="0"/>
|
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
<DimensionLayout dim="1">
|
<DimensionLayout dim="1">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
@ -158,6 +177,16 @@
|
|||||||
<Component id="dataSourcesHideSlackCheckbox" min="-2" max="-2" attributes="0"/>
|
<Component id="dataSourcesHideSlackCheckbox" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Component id="viewsHideSlackCheckbox" min="-2" max="-2" attributes="0"/>
|
<Component id="viewsHideSlackCheckbox" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||||
|
<Component id="hideOtherUsersTagsLabel" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="hideOtherUsersTagsCheckbox" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||||
|
<Component id="centralRepoLabel" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="commentsOccurencesColumnsCheckbox" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||||
|
<Component id="deletedFilesLimitLabel" min="-2" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
<Group type="102" alignment="0" attributes="0">
|
<Group type="102" alignment="0" attributes="0">
|
||||||
<Component id="selectFileLabel" min="-2" max="-2" attributes="0"/>
|
<Component id="selectFileLabel" min="-2" max="-2" attributes="0"/>
|
||||||
@ -169,20 +198,12 @@
|
|||||||
<Component id="displayTimeLabel" min="-2" max="-2" attributes="0"/>
|
<Component id="displayTimeLabel" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Component id="useLocalTimeRadioButton" min="-2" max="-2" attributes="0"/>
|
<Component id="useLocalTimeRadioButton" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Component id="useGMTTimeRadioButton" min="-2" max="-2" attributes="0"/>
|
<Component id="useAnotherTimeRadioButton" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="jScrollPane1" min="-2" pref="67" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
|
||||||
<Component id="hideOtherUsersTagsLabel" min="-2" max="-2" attributes="0"/>
|
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
|
||||||
<Component id="hideOtherUsersTagsCheckbox" min="-2" max="-2" attributes="0"/>
|
|
||||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
|
||||||
<Component id="centralRepoLabel" min="-2" max="-2" attributes="0"/>
|
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
|
||||||
<Component id="commentsOccurencesColumnsCheckbox" min="-2" max="-2" attributes="0"/>
|
|
||||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
|
||||||
<Component id="deletedFilesLimitLabel" min="-2" max="-2" attributes="0"/>
|
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Component id="deletedFilesLimitCheckbox" min="-2" pref="33" max="-2" attributes="0"/>
|
<Component id="deletedFilesLimitCheckbox" min="-2" pref="33" max="-2" attributes="0"/>
|
||||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||||
@ -295,14 +316,14 @@
|
|||||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="useLocalTimeRadioButtonActionPerformed"/>
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="useLocalTimeRadioButtonActionPerformed"/>
|
||||||
</Events>
|
</Events>
|
||||||
</Component>
|
</Component>
|
||||||
<Component class="javax.swing.JRadioButton" name="useGMTTimeRadioButton">
|
<Component class="javax.swing.JRadioButton" name="useAnotherTimeRadioButton">
|
||||||
<Properties>
|
<Properties>
|
||||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="ViewPreferencesPanel.useGMTTimeRadioButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="ViewPreferencesPanel.useAnotherTimeRadioButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
<Events>
|
<Events>
|
||||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="useGMTTimeRadioButtonActionPerformed"/>
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="useAnotherTimeRadioButtonActionPerformed"/>
|
||||||
</Events>
|
</Events>
|
||||||
</Component>
|
</Component>
|
||||||
<Component class="javax.swing.JCheckBox" name="hideOtherUsersTagsCheckbox">
|
<Component class="javax.swing.JCheckBox" name="hideOtherUsersTagsCheckbox">
|
||||||
@ -356,6 +377,28 @@
|
|||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Component>
|
</Component>
|
||||||
|
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
|
||||||
|
<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="timeZoneList">
|
||||||
|
<Properties>
|
||||||
|
<Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.editors2.ListModelEditor">
|
||||||
|
<StringArray count="0"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<Events>
|
||||||
|
<EventHandler event="valueChanged" listener="javax.swing.event.ListSelectionListener" parameters="javax.swing.event.ListSelectionEvent" handler="timeZoneListValueChanged"/>
|
||||||
|
</Events>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<String>"/>
|
||||||
|
</AuxValues>
|
||||||
|
</Component>
|
||||||
|
</SubComponents>
|
||||||
|
</Container>
|
||||||
</SubComponents>
|
</SubComponents>
|
||||||
</Container>
|
</Container>
|
||||||
<Container class="javax.swing.JPanel" name="currentCaseSettingsPanel">
|
<Container class="javax.swing.JPanel" name="currentCaseSettingsPanel">
|
||||||
|
@ -19,12 +19,14 @@
|
|||||||
package org.sleuthkit.autopsy.corecomponents;
|
package org.sleuthkit.autopsy.corecomponents;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.TimeZone;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import org.netbeans.spi.options.OptionsPanelController;
|
import org.netbeans.spi.options.OptionsPanelController;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.casemodule.CasePreferences;
|
import org.sleuthkit.autopsy.casemodule.CasePreferences;
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbUtil;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbUtil;
|
||||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.TimeZoneUtils;
|
||||||
import org.sleuthkit.autopsy.deletedFiles.DeletedFilePreferences;
|
import org.sleuthkit.autopsy.deletedFiles.DeletedFilePreferences;
|
||||||
import org.sleuthkit.autopsy.directorytree.DirectoryTreeTopComponent;
|
import org.sleuthkit.autopsy.directorytree.DirectoryTreeTopComponent;
|
||||||
|
|
||||||
@ -44,6 +46,8 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
|||||||
public ViewPreferencesPanel(boolean immediateUpdates) {
|
public ViewPreferencesPanel(boolean immediateUpdates) {
|
||||||
initComponents();
|
initComponents();
|
||||||
this.immediateUpdates = immediateUpdates;
|
this.immediateUpdates = immediateUpdates;
|
||||||
|
|
||||||
|
this.timeZoneList.setListData(TimeZoneUtils.createTimeZoneList().stream().toArray(String[]::new));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -54,8 +58,10 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
|||||||
useBestViewerRadioButton.setSelected(!keepPreferredViewer);
|
useBestViewerRadioButton.setSelected(!keepPreferredViewer);
|
||||||
|
|
||||||
boolean useLocalTime = UserPreferences.displayTimesInLocalTime();
|
boolean useLocalTime = UserPreferences.displayTimesInLocalTime();
|
||||||
|
timeZoneList.setEnabled(!useLocalTime);
|
||||||
|
timeZoneList.setSelectedValue(TimeZoneUtils.createTimeZoneString(TimeZone.getTimeZone(UserPreferences.getTimeZoneForDisplays())), true);
|
||||||
useLocalTimeRadioButton.setSelected(useLocalTime);
|
useLocalTimeRadioButton.setSelected(useLocalTime);
|
||||||
useGMTTimeRadioButton.setSelected(!useLocalTime);
|
useAnotherTimeRadioButton.setSelected(!useLocalTime);
|
||||||
|
|
||||||
dataSourcesHideKnownCheckbox.setSelected(UserPreferences.hideKnownFilesInDataSourcesTree());
|
dataSourcesHideKnownCheckbox.setSelected(UserPreferences.hideKnownFilesInDataSourcesTree());
|
||||||
viewsHideKnownCheckbox.setSelected(UserPreferences.hideKnownFilesInViewsTree());
|
viewsHideKnownCheckbox.setSelected(UserPreferences.hideKnownFilesInViewsTree());
|
||||||
@ -84,6 +90,9 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
|||||||
public void store() {
|
public void store() {
|
||||||
UserPreferences.setKeepPreferredContentViewer(keepCurrentViewerRadioButton.isSelected());
|
UserPreferences.setKeepPreferredContentViewer(keepCurrentViewerRadioButton.isSelected());
|
||||||
UserPreferences.setDisplayTimesInLocalTime(useLocalTimeRadioButton.isSelected());
|
UserPreferences.setDisplayTimesInLocalTime(useLocalTimeRadioButton.isSelected());
|
||||||
|
if (useAnotherTimeRadioButton.isSelected()) {
|
||||||
|
UserPreferences.setTimeZoneForDisplays(timeZoneList.getSelectedValue().substring(11).trim());
|
||||||
|
}
|
||||||
UserPreferences.setHideKnownFilesInDataSourcesTree(dataSourcesHideKnownCheckbox.isSelected());
|
UserPreferences.setHideKnownFilesInDataSourcesTree(dataSourcesHideKnownCheckbox.isSelected());
|
||||||
UserPreferences.setHideKnownFilesInViewsTree(viewsHideKnownCheckbox.isSelected());
|
UserPreferences.setHideKnownFilesInViewsTree(viewsHideKnownCheckbox.isSelected());
|
||||||
UserPreferences.setHideSlackFilesInDataSourcesTree(dataSourcesHideSlackCheckbox.isSelected());
|
UserPreferences.setHideSlackFilesInDataSourcesTree(dataSourcesHideSlackCheckbox.isSelected());
|
||||||
@ -135,19 +144,24 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
|||||||
viewsHideSlackCheckbox = new javax.swing.JCheckBox();
|
viewsHideSlackCheckbox = new javax.swing.JCheckBox();
|
||||||
displayTimeLabel = new javax.swing.JLabel();
|
displayTimeLabel = new javax.swing.JLabel();
|
||||||
useLocalTimeRadioButton = new javax.swing.JRadioButton();
|
useLocalTimeRadioButton = new javax.swing.JRadioButton();
|
||||||
useGMTTimeRadioButton = new javax.swing.JRadioButton();
|
useAnotherTimeRadioButton = new javax.swing.JRadioButton();
|
||||||
hideOtherUsersTagsCheckbox = new javax.swing.JCheckBox();
|
hideOtherUsersTagsCheckbox = new javax.swing.JCheckBox();
|
||||||
hideOtherUsersTagsLabel = new javax.swing.JLabel();
|
hideOtherUsersTagsLabel = new javax.swing.JLabel();
|
||||||
commentsOccurencesColumnsCheckbox = new javax.swing.JCheckBox();
|
commentsOccurencesColumnsCheckbox = new javax.swing.JCheckBox();
|
||||||
centralRepoLabel = new javax.swing.JLabel();
|
centralRepoLabel = new javax.swing.JLabel();
|
||||||
deletedFilesLimitCheckbox = new javax.swing.JCheckBox();
|
deletedFilesLimitCheckbox = new javax.swing.JCheckBox();
|
||||||
deletedFilesLimitLabel = new javax.swing.JLabel();
|
deletedFilesLimitLabel = new javax.swing.JLabel();
|
||||||
|
jScrollPane1 = new javax.swing.JScrollPane();
|
||||||
|
timeZoneList = new javax.swing.JList<>();
|
||||||
currentCaseSettingsPanel = new javax.swing.JPanel();
|
currentCaseSettingsPanel = new javax.swing.JPanel();
|
||||||
groupByDataSourceCheckbox = new javax.swing.JCheckBox();
|
groupByDataSourceCheckbox = new javax.swing.JCheckBox();
|
||||||
currentSessionSettingsPanel = new javax.swing.JPanel();
|
currentSessionSettingsPanel = new javax.swing.JPanel();
|
||||||
hideRejectedResultsCheckbox = new javax.swing.JCheckBox();
|
hideRejectedResultsCheckbox = new javax.swing.JCheckBox();
|
||||||
|
|
||||||
viewPreferencesScrollPane.setBorder(null);
|
viewPreferencesScrollPane.setBorder(null);
|
||||||
|
viewPreferencesScrollPane.setPreferredSize(new java.awt.Dimension(625, 452));
|
||||||
|
|
||||||
|
viewPreferencesPanel.setPreferredSize(new java.awt.Dimension(625, 452));
|
||||||
|
|
||||||
globalSettingsPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(ViewPreferencesPanel.class, "ViewPreferencesPanel.globalSettingsPanel.border.title"))); // NOI18N
|
globalSettingsPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(ViewPreferencesPanel.class, "ViewPreferencesPanel.globalSettingsPanel.border.title"))); // NOI18N
|
||||||
|
|
||||||
@ -210,10 +224,10 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
org.openide.awt.Mnemonics.setLocalizedText(useGMTTimeRadioButton, org.openide.util.NbBundle.getMessage(ViewPreferencesPanel.class, "ViewPreferencesPanel.useGMTTimeRadioButton.text")); // NOI18N
|
org.openide.awt.Mnemonics.setLocalizedText(useAnotherTimeRadioButton, org.openide.util.NbBundle.getMessage(ViewPreferencesPanel.class, "ViewPreferencesPanel.useAnotherTimeRadioButton.text")); // NOI18N
|
||||||
useGMTTimeRadioButton.addActionListener(new java.awt.event.ActionListener() {
|
useAnotherTimeRadioButton.addActionListener(new java.awt.event.ActionListener() {
|
||||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
useGMTTimeRadioButtonActionPerformed(evt);
|
useAnotherTimeRadioButtonActionPerformed(evt);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -244,6 +258,13 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
|||||||
|
|
||||||
org.openide.awt.Mnemonics.setLocalizedText(deletedFilesLimitLabel, org.openide.util.NbBundle.getMessage(ViewPreferencesPanel.class, "ViewPreferencesPanel.deletedFilesLimitLabel.text")); // NOI18N
|
org.openide.awt.Mnemonics.setLocalizedText(deletedFilesLimitLabel, org.openide.util.NbBundle.getMessage(ViewPreferencesPanel.class, "ViewPreferencesPanel.deletedFilesLimitLabel.text")); // NOI18N
|
||||||
|
|
||||||
|
timeZoneList.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
|
||||||
|
public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
|
||||||
|
timeZoneListValueChanged(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
jScrollPane1.setViewportView(timeZoneList);
|
||||||
|
|
||||||
javax.swing.GroupLayout globalSettingsPanelLayout = new javax.swing.GroupLayout(globalSettingsPanel);
|
javax.swing.GroupLayout globalSettingsPanelLayout = new javax.swing.GroupLayout(globalSettingsPanel);
|
||||||
globalSettingsPanel.setLayout(globalSettingsPanelLayout);
|
globalSettingsPanel.setLayout(globalSettingsPanelLayout);
|
||||||
globalSettingsPanelLayout.setHorizontalGroup(
|
globalSettingsPanelLayout.setHorizontalGroup(
|
||||||
@ -256,7 +277,15 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
|||||||
.addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
.addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addComponent(commentsOccurencesColumnsCheckbox)
|
.addComponent(commentsOccurencesColumnsCheckbox)
|
||||||
.addComponent(hideOtherUsersTagsCheckbox)
|
.addComponent(hideOtherUsersTagsCheckbox)
|
||||||
.addComponent(deletedFilesLimitCheckbox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
|
.addGroup(globalSettingsPanelLayout.createSequentialGroup()
|
||||||
|
.addComponent(deletedFilesLimitCheckbox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
|
.addGap(399, 399, 399))))
|
||||||
|
.addGroup(globalSettingsPanelLayout.createSequentialGroup()
|
||||||
|
.addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(globalSettingsPanelLayout.createSequentialGroup()
|
||||||
|
.addComponent(centralRepoLabel)
|
||||||
|
.addGap(135, 135, 135)
|
||||||
|
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 272, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||||
.addGroup(globalSettingsPanelLayout.createSequentialGroup()
|
.addGroup(globalSettingsPanelLayout.createSequentialGroup()
|
||||||
.addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
.addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addGroup(globalSettingsPanelLayout.createSequentialGroup()
|
.addGroup(globalSettingsPanelLayout.createSequentialGroup()
|
||||||
@ -283,14 +312,13 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
|||||||
.addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
.addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addComponent(keepCurrentViewerRadioButton)
|
.addComponent(keepCurrentViewerRadioButton)
|
||||||
.addComponent(useBestViewerRadioButton)
|
.addComponent(useBestViewerRadioButton)
|
||||||
.addComponent(useGMTTimeRadioButton)
|
.addComponent(useLocalTimeRadioButton)
|
||||||
.addComponent(useLocalTimeRadioButton)))
|
.addComponent(useAnotherTimeRadioButton)))
|
||||||
.addComponent(selectFileLabel)))
|
.addComponent(selectFileLabel)))
|
||||||
.addComponent(hideOtherUsersTagsLabel)
|
.addComponent(hideOtherUsersTagsLabel)
|
||||||
.addComponent(centralRepoLabel)
|
|
||||||
.addComponent(deletedFilesLimitLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 215, javax.swing.GroupLayout.PREFERRED_SIZE))
|
.addComponent(deletedFilesLimitLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 215, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||||
.addGap(0, 10, Short.MAX_VALUE)))
|
.addGap(0, 0, Short.MAX_VALUE)))
|
||||||
.addContainerGap())
|
.addContainerGap())))
|
||||||
);
|
);
|
||||||
globalSettingsPanelLayout.setVerticalGroup(
|
globalSettingsPanelLayout.setVerticalGroup(
|
||||||
globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
@ -308,7 +336,17 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
|||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(dataSourcesHideSlackCheckbox)
|
.addComponent(dataSourcesHideSlackCheckbox)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(viewsHideSlackCheckbox))
|
.addComponent(viewsHideSlackCheckbox)
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||||
|
.addComponent(hideOtherUsersTagsLabel)
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
|
.addComponent(hideOtherUsersTagsCheckbox)
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||||
|
.addComponent(centralRepoLabel)
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
|
.addComponent(commentsOccurencesColumnsCheckbox)
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||||
|
.addComponent(deletedFilesLimitLabel))
|
||||||
.addGroup(globalSettingsPanelLayout.createSequentialGroup()
|
.addGroup(globalSettingsPanelLayout.createSequentialGroup()
|
||||||
.addComponent(selectFileLabel)
|
.addComponent(selectFileLabel)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
@ -320,17 +358,9 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
|||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(useLocalTimeRadioButton)
|
.addComponent(useLocalTimeRadioButton)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(useGMTTimeRadioButton)))
|
.addComponent(useAnotherTimeRadioButton)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
|
||||||
.addComponent(hideOtherUsersTagsLabel)
|
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(hideOtherUsersTagsCheckbox)
|
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 67, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
|
||||||
.addComponent(centralRepoLabel)
|
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
|
||||||
.addComponent(commentsOccurencesColumnsCheckbox)
|
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
|
||||||
.addComponent(deletedFilesLimitLabel)
|
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(deletedFilesLimitCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, 33, javax.swing.GroupLayout.PREFERRED_SIZE)
|
.addComponent(deletedFilesLimitCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, 33, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
.addGap(0, 0, 0))
|
.addGap(0, 0, 0))
|
||||||
@ -415,11 +445,11 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
|||||||
this.setLayout(layout);
|
this.setLayout(layout);
|
||||||
layout.setHorizontalGroup(
|
layout.setHorizontalGroup(
|
||||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addComponent(viewPreferencesScrollPane)
|
.addComponent(viewPreferencesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
);
|
);
|
||||||
layout.setVerticalGroup(
|
layout.setVerticalGroup(
|
||||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addComponent(viewPreferencesScrollPane)
|
.addComponent(viewPreferencesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
);
|
);
|
||||||
}// </editor-fold>//GEN-END:initComponents
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
@ -445,7 +475,8 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
|||||||
|
|
||||||
private void useLocalTimeRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_useLocalTimeRadioButtonActionPerformed
|
private void useLocalTimeRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_useLocalTimeRadioButtonActionPerformed
|
||||||
useLocalTimeRadioButton.setSelected(true);
|
useLocalTimeRadioButton.setSelected(true);
|
||||||
useGMTTimeRadioButton.setSelected(false);
|
useAnotherTimeRadioButton.setSelected(false);
|
||||||
|
timeZoneList.setEnabled(false);
|
||||||
if (immediateUpdates) {
|
if (immediateUpdates) {
|
||||||
UserPreferences.setDisplayTimesInLocalTime(true);
|
UserPreferences.setDisplayTimesInLocalTime(true);
|
||||||
} else {
|
} else {
|
||||||
@ -453,15 +484,16 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
|||||||
}
|
}
|
||||||
}//GEN-LAST:event_useLocalTimeRadioButtonActionPerformed
|
}//GEN-LAST:event_useLocalTimeRadioButtonActionPerformed
|
||||||
|
|
||||||
private void useGMTTimeRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_useGMTTimeRadioButtonActionPerformed
|
private void useAnotherTimeRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_useAnotherTimeRadioButtonActionPerformed
|
||||||
useLocalTimeRadioButton.setSelected(false);
|
useLocalTimeRadioButton.setSelected(false);
|
||||||
useGMTTimeRadioButton.setSelected(true);
|
useAnotherTimeRadioButton.setSelected(true);
|
||||||
|
timeZoneList.setEnabled(true);
|
||||||
if (immediateUpdates) {
|
if (immediateUpdates) {
|
||||||
UserPreferences.setDisplayTimesInLocalTime(false);
|
UserPreferences.setDisplayTimesInLocalTime(false);
|
||||||
} else {
|
} else {
|
||||||
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
|
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
|
||||||
}
|
}
|
||||||
}//GEN-LAST:event_useGMTTimeRadioButtonActionPerformed
|
}//GEN-LAST:event_useAnotherTimeRadioButtonActionPerformed
|
||||||
|
|
||||||
private void dataSourcesHideKnownCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dataSourcesHideKnownCheckboxActionPerformed
|
private void dataSourcesHideKnownCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dataSourcesHideKnownCheckboxActionPerformed
|
||||||
if (immediateUpdates) {
|
if (immediateUpdates) {
|
||||||
@ -535,6 +567,14 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
|||||||
}
|
}
|
||||||
}//GEN-LAST:event_deletedFilesLimitCheckboxActionPerformed
|
}//GEN-LAST:event_deletedFilesLimitCheckboxActionPerformed
|
||||||
|
|
||||||
|
private void timeZoneListValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_timeZoneListValueChanged
|
||||||
|
if (immediateUpdates && useAnotherTimeRadioButton.isSelected()) {
|
||||||
|
UserPreferences.setTimeZoneForDisplays(timeZoneList.getSelectedValue().substring(11).trim());
|
||||||
|
} else {
|
||||||
|
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
|
||||||
|
}
|
||||||
|
}//GEN-LAST:event_timeZoneListValueChanged
|
||||||
|
|
||||||
|
|
||||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
private javax.swing.JLabel centralRepoLabel;
|
private javax.swing.JLabel centralRepoLabel;
|
||||||
@ -553,10 +593,12 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
|||||||
private javax.swing.JLabel hideOtherUsersTagsLabel;
|
private javax.swing.JLabel hideOtherUsersTagsLabel;
|
||||||
private javax.swing.JCheckBox hideRejectedResultsCheckbox;
|
private javax.swing.JCheckBox hideRejectedResultsCheckbox;
|
||||||
private javax.swing.JLabel hideSlackFilesLabel;
|
private javax.swing.JLabel hideSlackFilesLabel;
|
||||||
|
private javax.swing.JScrollPane jScrollPane1;
|
||||||
private javax.swing.JRadioButton keepCurrentViewerRadioButton;
|
private javax.swing.JRadioButton keepCurrentViewerRadioButton;
|
||||||
private javax.swing.JLabel selectFileLabel;
|
private javax.swing.JLabel selectFileLabel;
|
||||||
|
private javax.swing.JList<String> timeZoneList;
|
||||||
|
private javax.swing.JRadioButton useAnotherTimeRadioButton;
|
||||||
private javax.swing.JRadioButton useBestViewerRadioButton;
|
private javax.swing.JRadioButton useBestViewerRadioButton;
|
||||||
private javax.swing.JRadioButton useGMTTimeRadioButton;
|
|
||||||
private javax.swing.JRadioButton useLocalTimeRadioButton;
|
private javax.swing.JRadioButton useLocalTimeRadioButton;
|
||||||
private javax.swing.JPanel viewPreferencesPanel;
|
private javax.swing.JPanel viewPreferencesPanel;
|
||||||
private javax.swing.JScrollPane viewPreferencesScrollPane;
|
private javax.swing.JScrollPane viewPreferencesScrollPane;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2012-2015 Basis Technology Corp.
|
* Copyright 2012-2018 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -18,14 +18,22 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.coreutils;
|
package org.sleuthkit.autopsy.coreutils;
|
||||||
|
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.StringTokenizer;
|
||||||
|
|
||||||
public class NetworkUtils {
|
public class NetworkUtils {
|
||||||
|
|
||||||
|
private NetworkUtils() {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the host name variable. Sometimes the network can be finicky, so the
|
* Set the host name variable. Sometimes the network can be finicky, so the
|
||||||
* answer returned by getHostName() could throw an exception or be null.
|
* answer returned by getHostName() could throw an exception or be null.
|
||||||
* Have it read the environment variable if getHostName() is unsuccessful.
|
* Have it read the environment variable if getHostName() is unsuccessful.
|
||||||
|
*
|
||||||
|
* @return the local host name
|
||||||
*/
|
*/
|
||||||
public static String getLocalHostName() {
|
public static String getLocalHostName() {
|
||||||
String hostName = "";
|
String hostName = "";
|
||||||
@ -41,4 +49,78 @@ public class NetworkUtils {
|
|||||||
}
|
}
|
||||||
return hostName;
|
return hostName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to manually extract the domain from a URL.
|
||||||
|
*
|
||||||
|
* @param url
|
||||||
|
* @return empty string if no domain could be found
|
||||||
|
*/
|
||||||
|
private static String getBaseDomain(String url) {
|
||||||
|
String host = null;
|
||||||
|
|
||||||
|
//strip protocol
|
||||||
|
String cleanUrl = url.replaceFirst(".*:\\/\\/", "");
|
||||||
|
|
||||||
|
//strip after slashes
|
||||||
|
String dirToks[] = cleanUrl.split("\\/");
|
||||||
|
if (dirToks.length > 0) {
|
||||||
|
host = dirToks[0];
|
||||||
|
} else {
|
||||||
|
host = cleanUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the domain part from host (last 2)
|
||||||
|
StringTokenizer tok = new StringTokenizer(host, ".");
|
||||||
|
StringBuilder hostB = new StringBuilder();
|
||||||
|
int toks = tok.countTokens();
|
||||||
|
|
||||||
|
for (int count = 0; count < toks; ++count) {
|
||||||
|
String part = tok.nextToken();
|
||||||
|
int diff = toks - count;
|
||||||
|
if (diff < 3) {
|
||||||
|
hostB.append(part);
|
||||||
|
}
|
||||||
|
if (diff == 2) {
|
||||||
|
hostB.append(".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String base = hostB.toString();
|
||||||
|
// verify there are no special characters in there
|
||||||
|
if (base.matches(".*[~`!@#$%^&\\*\\(\\)\\+={}\\[\\];:\\?<>,/ ].*")) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to extract the domain from a URL.
|
||||||
|
* Will start by using the built-in URL class, and if that fails will
|
||||||
|
* try to extract it manually.
|
||||||
|
*
|
||||||
|
* @param urlString The URL to extract the domain from
|
||||||
|
* @return empty string if no domain name was found
|
||||||
|
*/
|
||||||
|
public static String extractDomain(String urlString) {
|
||||||
|
if (urlString == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
String result = "";
|
||||||
|
|
||||||
|
try {
|
||||||
|
URL url = new URL(urlString);
|
||||||
|
result = url.getHost();
|
||||||
|
} catch (MalformedURLException ex) {
|
||||||
|
//do not log if not a valid URL - we will try to extract it ourselves
|
||||||
|
}
|
||||||
|
|
||||||
|
//was not a valid URL, try a less picky method
|
||||||
|
if (result == null || result.trim().isEmpty()) {
|
||||||
|
return getBaseDomain(urlString);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2016 Basis Technology Corp.
|
* Copyright 2011-2018 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -20,7 +20,13 @@ package org.sleuthkit.autopsy.coreutils;
|
|||||||
|
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.GregorianCalendar;
|
import java.util.GregorianCalendar;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.SimpleTimeZone;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility methods for workig with time zones.
|
* Utility methods for workig with time zones.
|
||||||
@ -41,7 +47,7 @@ public class TimeZoneUtils {
|
|||||||
java.util.TimeZone zone = java.util.TimeZone.getTimeZone(timeZoneId);
|
java.util.TimeZone zone = java.util.TimeZone.getTimeZone(timeZoneId);
|
||||||
int offset = zone.getRawOffset() / 1000;
|
int offset = zone.getRawOffset() / 1000;
|
||||||
int hour = offset / 3600;
|
int hour = offset / 3600;
|
||||||
int min = (offset % 3600) / 60;
|
int min = Math.abs((offset % 3600) / 60);
|
||||||
|
|
||||||
DateFormat dfm = new SimpleDateFormat("z");
|
DateFormat dfm = new SimpleDateFormat("z");
|
||||||
dfm.setTimeZone(zone);
|
dfm.setTimeZone(zone);
|
||||||
@ -60,6 +66,73 @@ public class TimeZoneUtils {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a time zone string containing the GMT offset and ID.
|
||||||
|
*
|
||||||
|
* @param timeZone The time zone.
|
||||||
|
*
|
||||||
|
* @return The time zone string.
|
||||||
|
*/
|
||||||
|
public static String createTimeZoneString(TimeZone timeZone) {
|
||||||
|
int offset = timeZone.getRawOffset() / 1000;
|
||||||
|
int hour = offset / 3600;
|
||||||
|
int minutes = Math.abs((offset % 3600) / 60);
|
||||||
|
|
||||||
|
return String.format("(GMT%+d:%02d) %s", hour, minutes, timeZone.getID()); //NON-NLS
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a list of time zones.
|
||||||
|
*/
|
||||||
|
public static List<String> createTimeZoneList() {
|
||||||
|
/*
|
||||||
|
* Create a list of time zones.
|
||||||
|
*/
|
||||||
|
List<TimeZone> timeZoneList = new ArrayList<>();
|
||||||
|
|
||||||
|
String[] ids = SimpleTimeZone.getAvailableIDs();
|
||||||
|
for (String id : ids) {
|
||||||
|
/*
|
||||||
|
* DateFormat dfm = new SimpleDateFormat("z");
|
||||||
|
* dfm.setTimeZone(zone); boolean hasDaylight =
|
||||||
|
* zone.useDaylightTime(); String first = dfm.format(new Date(2010,
|
||||||
|
* 1, 1)); String second = dfm.format(new Date(2011, 6, 6)); int mid
|
||||||
|
* = hour * -1; String result = first + Integer.toString(mid);
|
||||||
|
* if(hasDaylight){ result = result + second; }
|
||||||
|
* timeZoneComboBox.addItem(item + " (" + result + ")");
|
||||||
|
*/
|
||||||
|
timeZoneList.add(TimeZone.getTimeZone(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sort the list of time zones first by offset, then by ID.
|
||||||
|
*/
|
||||||
|
Collections.sort(timeZoneList, new Comparator<TimeZone>(){
|
||||||
|
@Override
|
||||||
|
public int compare(TimeZone o1, TimeZone o2){
|
||||||
|
int offsetDelta = Integer.compare(o1.getRawOffset(), o2.getRawOffset());
|
||||||
|
|
||||||
|
if (offsetDelta == 0) {
|
||||||
|
return o1.getID().compareToIgnoreCase(o2.getID());
|
||||||
|
}
|
||||||
|
|
||||||
|
return offsetDelta;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a list of Strings encompassing both the GMT offset and the
|
||||||
|
* time zone ID.
|
||||||
|
*/
|
||||||
|
List<String> outputList = new ArrayList<>();
|
||||||
|
|
||||||
|
for (TimeZone timeZone : timeZoneList) {
|
||||||
|
outputList.add(createTimeZoneString(timeZone));
|
||||||
|
}
|
||||||
|
|
||||||
|
return outputList;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prevents instantiation.
|
* Prevents instantiation.
|
||||||
*/
|
*/
|
||||||
|
@ -145,7 +145,7 @@ public final class ContentUtils {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (!shouldDisplayTimesInLocalTime()) {
|
if (!shouldDisplayTimesInLocalTime()) {
|
||||||
return TimeZone.getTimeZone("GMT");
|
return TimeZone.getTimeZone(UserPreferences.getTimeZoneForDisplays());
|
||||||
} else {
|
} else {
|
||||||
final Content dataSource = content.getDataSource();
|
final Content dataSource = content.getDataSource();
|
||||||
if ((dataSource != null) && (dataSource instanceof Image)) {
|
if ((dataSource != null) && (dataSource instanceof Image)) {
|
||||||
|
@ -20,8 +20,7 @@ package org.sleuthkit.autopsy.datasourceprocessors;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.SimpleTimeZone;
|
import java.util.List;
|
||||||
import java.util.TimeZone;
|
|
||||||
import javax.swing.JFileChooser;
|
import javax.swing.JFileChooser;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.event.DocumentEvent;
|
import javax.swing.event.DocumentEvent;
|
||||||
@ -32,6 +31,7 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
|||||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
||||||
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
|
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
|
||||||
import org.sleuthkit.autopsy.coreutils.PathValidator;
|
import org.sleuthkit.autopsy.coreutils.PathValidator;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.TimeZoneUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows examiner to supply a raw data source.
|
* Allows examiner to supply a raw data source.
|
||||||
@ -82,26 +82,13 @@ final class RawDSInputPanel extends JPanel implements DocumentListener {
|
|||||||
* machine time zone to be selected.
|
* machine time zone to be selected.
|
||||||
*/
|
*/
|
||||||
private void createTimeZoneList() {
|
private void createTimeZoneList() {
|
||||||
// load and add all timezone
|
List<String> timeZoneList = TimeZoneUtils.createTimeZoneList();
|
||||||
String[] ids = SimpleTimeZone.getAvailableIDs();
|
for (String timeZone : timeZoneList) {
|
||||||
for (String id : ids) {
|
timeZoneComboBox.addItem(timeZone);
|
||||||
TimeZone zone = TimeZone.getTimeZone(id);
|
|
||||||
int offset = zone.getRawOffset() / 1000;
|
|
||||||
int hour = offset / 3600;
|
|
||||||
int minutes = (offset % 3600) / 60;
|
|
||||||
String item = String.format("(GMT%+d:%02d) %s", hour, minutes, id);
|
|
||||||
|
|
||||||
timeZoneComboBox.addItem(item);
|
|
||||||
}
|
}
|
||||||
// get the current timezone
|
|
||||||
TimeZone thisTimeZone = Calendar.getInstance().getTimeZone();
|
|
||||||
int thisOffset = thisTimeZone.getRawOffset() / 1000;
|
|
||||||
int thisHour = thisOffset / 3600;
|
|
||||||
int thisMinutes = (thisOffset % 3600) / 60;
|
|
||||||
String formatted = String.format("(GMT%+d:%02d) %s", thisHour, thisMinutes, thisTimeZone.getID());
|
|
||||||
|
|
||||||
// set the selected timezone
|
// set the selected timezone
|
||||||
timeZoneComboBox.setSelectedItem(formatted);
|
timeZoneComboBox.setSelectedItem(TimeZoneUtils.createTimeZoneString(Calendar.getInstance().getTimeZone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -167,6 +167,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
public void preferenceChange(PreferenceChangeEvent evt) {
|
public void preferenceChange(PreferenceChangeEvent evt) {
|
||||||
switch (evt.getKey()) {
|
switch (evt.getKey()) {
|
||||||
case UserPreferences.DISPLAY_TIMES_IN_LOCAL_TIME:
|
case UserPreferences.DISPLAY_TIMES_IN_LOCAL_TIME:
|
||||||
|
case UserPreferences.TIME_ZONE_FOR_DISPLAYS:
|
||||||
case UserPreferences.HIDE_KNOWN_FILES_IN_DATA_SRCS_TREE:
|
case UserPreferences.HIDE_KNOWN_FILES_IN_DATA_SRCS_TREE:
|
||||||
case UserPreferences.HIDE_SLACK_FILES_IN_DATA_SRCS_TREE:
|
case UserPreferences.HIDE_SLACK_FILES_IN_DATA_SRCS_TREE:
|
||||||
case UserPreferences.HIDE_CENTRAL_REPO_COMMENTS_AND_OCCURRENCES:
|
case UserPreferences.HIDE_CENTRAL_REPO_COMMENTS_AND_OCCURRENCES:
|
||||||
|
@ -29,7 +29,6 @@ import java.util.ArrayList;
|
|||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.SimpleTimeZone;
|
import java.util.SimpleTimeZone;
|
||||||
@ -44,6 +43,7 @@ import org.openide.util.NbBundle;
|
|||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.openide.util.NbBundle.Messages;
|
import org.openide.util.NbBundle.Messages;
|
||||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.TimeZoneUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filters file date properties (modified/created/etc.. times)
|
* Filters file date properties (modified/created/etc.. times)
|
||||||
@ -144,30 +144,15 @@ class DateSearchFilter extends AbstractFileSearchFilter<DateSearchPanel> {
|
|||||||
Case currentCase = Case.getCurrentCaseThrows(); // get the most updated case
|
Case currentCase = Case.getCurrentCaseThrows(); // get the most updated case
|
||||||
|
|
||||||
Set<TimeZone> caseTimeZones = currentCase.getTimeZones();
|
Set<TimeZone> caseTimeZones = currentCase.getTimeZones();
|
||||||
Iterator<TimeZone> iterator = caseTimeZones.iterator();
|
for (TimeZone timeZone : caseTimeZones) {
|
||||||
while (iterator.hasNext()) {
|
timeZones.add(TimeZoneUtils.createTimeZoneString(timeZone));
|
||||||
TimeZone zone = iterator.next();
|
|
||||||
int offset = zone.getRawOffset() / 1000;
|
|
||||||
int hour = offset / 3600;
|
|
||||||
int minutes = (offset % 3600) / 60;
|
|
||||||
String item = String.format("(GMT%+d:%02d) %s", hour, minutes, zone.getID()); //NON-NLS
|
|
||||||
timeZones.add(item);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (caseTimeZones.size() > 0) {
|
if (caseTimeZones.size() > 0) {
|
||||||
timeZones.add(SEPARATOR);
|
timeZones.add(SEPARATOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
// load and add all timezone
|
timeZones.addAll(TimeZoneUtils.createTimeZoneList());
|
||||||
String[] ids = SimpleTimeZone.getAvailableIDs();
|
|
||||||
for (String id : ids) {
|
|
||||||
TimeZone zone = TimeZone.getTimeZone(id);
|
|
||||||
int offset = zone.getRawOffset() / 1000;
|
|
||||||
int hour = offset / 3600;
|
|
||||||
int minutes = (offset % 3600) / 60;
|
|
||||||
String item = String.format("(GMT%+d:%02d) %s", hour, minutes, id); //NON-NLS
|
|
||||||
timeZones.add(item);
|
|
||||||
}
|
|
||||||
} catch (NoCurrentCaseException ex) {
|
} catch (NoCurrentCaseException ex) {
|
||||||
// No current case.
|
// No current case.
|
||||||
}
|
}
|
||||||
|
@ -269,8 +269,7 @@ class MSOfficeEmbeddedContentExtractor {
|
|||||||
HWPFDocument doc = new HWPFDocument(new ReadContentInputStream(af));
|
HWPFDocument doc = new HWPFDocument(new ReadContentInputStream(af));
|
||||||
PicturesTable pictureTable = doc.getPicturesTable();
|
PicturesTable pictureTable = doc.getPicturesTable();
|
||||||
listOfAllPictures = pictureTable.getAllPictures();
|
listOfAllPictures = pictureTable.getAllPictures();
|
||||||
} catch (IOException | IllegalArgumentException
|
} catch (Exception ex) {
|
||||||
| IndexOutOfBoundsException | NullPointerException ex) {
|
|
||||||
// IOException:
|
// IOException:
|
||||||
// Thrown when the document has issues being read.
|
// Thrown when the document has issues being read.
|
||||||
|
|
||||||
@ -286,10 +285,9 @@ class MSOfficeEmbeddedContentExtractor {
|
|||||||
// These get thrown in certain images. The reason is unknown. It is
|
// These get thrown in certain images. The reason is unknown. It is
|
||||||
// likely due to problems with the file formats that POI is poorly
|
// likely due to problems with the file formats that POI is poorly
|
||||||
// handling.
|
// handling.
|
||||||
return null;
|
|
||||||
} catch (Throwable ex) {
|
//Any runtime exception escaping
|
||||||
// instantiating POI containers throw RuntimeExceptions
|
LOGGER.log(Level.WARNING, "Word document container could not be initialized. Reason: {0}", ex.getMessage()); //NON-NLS
|
||||||
LOGGER.log(Level.SEVERE, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.docContainer.init.err", af.getName()), ex); //NON-NLS
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -333,8 +331,7 @@ class MSOfficeEmbeddedContentExtractor {
|
|||||||
try {
|
try {
|
||||||
HSLFSlideShow ppt = new HSLFSlideShow(new ReadContentInputStream(af));
|
HSLFSlideShow ppt = new HSLFSlideShow(new ReadContentInputStream(af));
|
||||||
listOfAllPictures = ppt.getPictureData();
|
listOfAllPictures = ppt.getPictureData();
|
||||||
} catch (IOException | IllegalArgumentException
|
} catch (Exception ex) {
|
||||||
| IndexOutOfBoundsException ex) {
|
|
||||||
// IllegalArgumentException:
|
// IllegalArgumentException:
|
||||||
// This will catch OldFileFormatException, which is thrown when the
|
// This will catch OldFileFormatException, which is thrown when the
|
||||||
// document version is unsupported. The IllegalArgumentException may
|
// document version is unsupported. The IllegalArgumentException may
|
||||||
@ -346,10 +343,7 @@ class MSOfficeEmbeddedContentExtractor {
|
|||||||
// This gets thrown in certain images. The reason is unknown. It is
|
// This gets thrown in certain images. The reason is unknown. It is
|
||||||
// likely due to problems with the file formats that POI is poorly
|
// likely due to problems with the file formats that POI is poorly
|
||||||
// handling.
|
// handling.
|
||||||
return null;
|
LOGGER.log(Level.WARNING, "PPT container could not be initialized. Reason: {0}", ex.getMessage()); //NON-NLS
|
||||||
} catch (Throwable ex) {
|
|
||||||
// instantiating POI containers throw RuntimeExceptions
|
|
||||||
LOGGER.log(Level.SEVERE, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.pptContainer.init.err", af.getName()), ex); //NON-NLS
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -422,9 +416,7 @@ class MSOfficeEmbeddedContentExtractor {
|
|||||||
try {
|
try {
|
||||||
Workbook xls = new HSSFWorkbook(new ReadContentInputStream(af));
|
Workbook xls = new HSSFWorkbook(new ReadContentInputStream(af));
|
||||||
listOfAllPictures = xls.getAllPictures();
|
listOfAllPictures = xls.getAllPictures();
|
||||||
} catch (IOException | LeftoverDataException
|
} catch (Exception ex) {
|
||||||
| RecordFormatException | IllegalArgumentException
|
|
||||||
| IndexOutOfBoundsException ex) {
|
|
||||||
// IllegalArgumentException:
|
// IllegalArgumentException:
|
||||||
// This will catch OldFileFormatException, which is thrown when the
|
// This will catch OldFileFormatException, which is thrown when the
|
||||||
// document version is unsupported. The IllegalArgumentException may
|
// document version is unsupported. The IllegalArgumentException may
|
||||||
@ -443,10 +435,7 @@ class MSOfficeEmbeddedContentExtractor {
|
|||||||
// These get thrown in certain images. The reason is unknown. It is
|
// These get thrown in certain images. The reason is unknown. It is
|
||||||
// likely due to problems with the file formats that POI is poorly
|
// likely due to problems with the file formats that POI is poorly
|
||||||
// handling.
|
// handling.
|
||||||
return null;
|
LOGGER.log(Level.WARNING, "Excel (.xls) document container could not be initialized. Reason: {0}", ex.getMessage()); //NON-NLS
|
||||||
} catch (Throwable ex) {
|
|
||||||
// instantiating POI containers throw RuntimeExceptions
|
|
||||||
LOGGER.log(Level.SEVERE, String.format("%s%s", NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.xlsContainer.init.err", af.getName()), af.getName()), ex); //NON-NLS
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,6 +180,15 @@ class SevenZipExtractor {
|
|||||||
* @return true if potential zip bomb, false otherwise
|
* @return true if potential zip bomb, false otherwise
|
||||||
*/
|
*/
|
||||||
private boolean isZipBombArchiveItemCheck(AbstractFile archiveFile, ISevenZipInArchive inArchive, int inArchiveItemIndex, ConcurrentHashMap<Long, Archive> depthMap, String escapedFilePath) {
|
private boolean isZipBombArchiveItemCheck(AbstractFile archiveFile, ISevenZipInArchive inArchive, int inArchiveItemIndex, ConcurrentHashMap<Long, Archive> depthMap, String escapedFilePath) {
|
||||||
|
//If a file is corrupted as a result of reconstructing it from unallocated space, then
|
||||||
|
//7zip does a poor job estimating the original uncompressed file size.
|
||||||
|
//As a result, many corrupted files have wonky compression ratios and could flood the UI
|
||||||
|
//with false zip bomb notifications. The decision was made to skip compression ratio checks
|
||||||
|
//for unallocated zip files. Instead, we let the depth be an indicator of a zip bomb.
|
||||||
|
if(archiveFile.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.UNALLOC)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final Long archiveItemSize = (Long) inArchive.getProperty(
|
final Long archiveItemSize = (Long) inArchive.getProperty(
|
||||||
inArchiveItemIndex, PropID.SIZE);
|
inArchiveItemIndex, PropID.SIZE);
|
||||||
@ -540,7 +549,6 @@ class SevenZipExtractor {
|
|||||||
inArchive = SevenZip.openInArchive(options, stream, password);
|
inArchive = SevenZip.openInArchive(options, stream, password);
|
||||||
}
|
}
|
||||||
numItems = inArchive.getNumberOfItems();
|
numItems = inArchive.getNumberOfItems();
|
||||||
logger.log(Level.INFO, "Count of items in archive: {0}: {1}", new Object[]{escapedArchiveFilePath, numItems}); //NON-NLS
|
|
||||||
progress.start(numItems);
|
progress.start(numItems);
|
||||||
progressStarted = true;
|
progressStarted = true;
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ import com.healthmarketscience.jackcess.util.MemFileChannel;
|
|||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.nio.BufferUnderflowException;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import org.apache.tika.exception.EncryptedDocumentException;
|
import org.apache.tika.exception.EncryptedDocumentException;
|
||||||
import org.apache.tika.exception.TikaException;
|
import org.apache.tika.exception.TikaException;
|
||||||
@ -313,7 +314,12 @@ final class EncryptionDetectionFileIngestModule extends FileIngestModuleAdapter
|
|||||||
DatabaseBuilder databaseBuilder = new DatabaseBuilder();
|
DatabaseBuilder databaseBuilder = new DatabaseBuilder();
|
||||||
databaseBuilder.setChannel(memFileChannel);
|
databaseBuilder.setChannel(memFileChannel);
|
||||||
databaseBuilder.setCodecProvider(codecProvider);
|
databaseBuilder.setCodecProvider(codecProvider);
|
||||||
Database accessDatabase = databaseBuilder.open();
|
Database accessDatabase;
|
||||||
|
try {
|
||||||
|
accessDatabase = databaseBuilder.open();
|
||||||
|
} catch (IOException | BufferUnderflowException | IndexOutOfBoundsException ignored) {
|
||||||
|
return passwordProtected;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* No exception has been thrown at this point, so the file
|
* No exception has been thrown at this point, so the file
|
||||||
* is either a JET database, or an unprotected ACE database.
|
* is either a JET database, or an unprotected ACE database.
|
||||||
|
@ -91,7 +91,7 @@ HashDbImportDatabaseDialog.errorMessage.failedToOpenHashDbMsg=Failed to open has
|
|||||||
HashLookupModuleFactory.moduleName.text=Hash Lookup
|
HashLookupModuleFactory.moduleName.text=Hash Lookup
|
||||||
HashLookupModuleFactory.moduleDescription.text=Identifies known and notable files using supplied hash sets, such as a standard NSRL hash set.
|
HashLookupModuleFactory.moduleDescription.text=Identifies known and notable files using supplied hash sets, such as a standard NSRL hash set.
|
||||||
HashDbIngestModule.fileReadErrorMsg=Read Error\: {0}
|
HashDbIngestModule.fileReadErrorMsg=Read Error\: {0}
|
||||||
HashDbIngestModule.calcHashValueErr=Error encountered while calculating the hash value for {0}.
|
HashDbIngestModule.calcHashValueErr=Error encountered while calculating the hash value for {0} ({1}).
|
||||||
HashDbIngestModule.hashLookupErrorMsg=Hash Lookup Error\: {0}
|
HashDbIngestModule.hashLookupErrorMsg=Hash Lookup Error\: {0}
|
||||||
HashDbIngestModule.settingKnownBadStateErr=Error encountered while setting notable state for {0}.
|
HashDbIngestModule.settingKnownBadStateErr=Error encountered while setting notable state for {0}.
|
||||||
HashDbIngestModule.lookingUpKnownBadHashValueErr=Error encountered while looking up notable hash value for {0}.
|
HashDbIngestModule.lookingUpKnownBadHashValueErr=Error encountered while looking up notable hash value for {0}.
|
||||||
|
@ -227,7 +227,9 @@ public class HashDbIngestModule implements FileIngestModule {
|
|||||||
services.postMessage(IngestMessage.createErrorMessage(
|
services.postMessage(IngestMessage.createErrorMessage(
|
||||||
HashLookupModuleFactory.getModuleName(),
|
HashLookupModuleFactory.getModuleName(),
|
||||||
NbBundle.getMessage(this.getClass(), "HashDbIngestModule.fileReadErrorMsg", name),
|
NbBundle.getMessage(this.getClass(), "HashDbIngestModule.fileReadErrorMsg", name),
|
||||||
NbBundle.getMessage(this.getClass(), "HashDbIngestModule.calcHashValueErr", name)));
|
NbBundle.getMessage(this.getClass(), "HashDbIngestModule.calcHashValueErr",
|
||||||
|
file.getParentPath() + file.getName(),
|
||||||
|
file.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.ALLOC)?"Allocated File" : "Deleted File")));
|
||||||
return ProcessResult.ERROR;
|
return ProcessResult.ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -649,6 +649,15 @@ public final class FilesSet implements Serializable {
|
|||||||
this.textMatcher = new FilesSet.Rule.RegexMatcher(regex);
|
this.textMatcher = new FilesSet.Rule.RegexMatcher(regex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a case-insensitive multi-value text condition.
|
||||||
|
*
|
||||||
|
* @param values The list of values in which to look for a match.
|
||||||
|
*/
|
||||||
|
AbstractTextCondition(List<String> values) {
|
||||||
|
this.textMatcher = new FilesSet.Rule.CaseInsensitiveMultiValueStringComparisionMatcher(values);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the text the condition matches.
|
* Get the text the condition matches.
|
||||||
*
|
*
|
||||||
@ -820,11 +829,11 @@ public final class FilesSet implements Serializable {
|
|||||||
*
|
*
|
||||||
* @param extension The file name extension to be matched.
|
* @param extension The file name extension to be matched.
|
||||||
*/
|
*/
|
||||||
public ExtensionCondition(String extension) {
|
public ExtensionCondition(List<String> extensions) {
|
||||||
// If there is a leading ".", strip it since
|
// If there is a leading ".", strip it since
|
||||||
// AbstractFile.getFileNameExtension() returns just the
|
// AbstractFile.getFileNameExtension() returns just the
|
||||||
// extension chars and not the dot.
|
// extension chars and not the dot.
|
||||||
super(extension.startsWith(".") ? extension.substring(1) : extension, false);
|
super(extensions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -948,6 +957,60 @@ public final class FilesSet implements Serializable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A text matcher that looks for a single case-insensitive string match
|
||||||
|
* in a multi-value list.
|
||||||
|
*/
|
||||||
|
private static class CaseInsensitiveMultiValueStringComparisionMatcher implements TextMatcher {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private final List<String> valuesToMatch;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a text matcher that looks for a single case-insensitive
|
||||||
|
* string match in a multi-value list.
|
||||||
|
*
|
||||||
|
* @param valuesToMatch The list of values in which to look for a
|
||||||
|
* match.
|
||||||
|
*/
|
||||||
|
CaseInsensitiveMultiValueStringComparisionMatcher(List<String> valuesToMatch) {
|
||||||
|
List<String> values = new ArrayList<>(valuesToMatch);
|
||||||
|
for (int i=0; i < values.size(); i++) {
|
||||||
|
// Remove leading and trailing whitespace.
|
||||||
|
String tempValue = values.get(i).trim();
|
||||||
|
|
||||||
|
// Strip "." from the start of the extension if it exists.
|
||||||
|
if (tempValue.startsWith(".")) {
|
||||||
|
tempValue = tempValue.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
values.set(i, tempValue);
|
||||||
|
}
|
||||||
|
this.valuesToMatch = values;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTextToMatch() {
|
||||||
|
return String.join(",", this.valuesToMatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRegex() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean textMatches(String subject) {
|
||||||
|
for (String value : valuesToMatch) {
|
||||||
|
if (value.equalsIgnoreCase(subject)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A text matcher that does regular expression matching.
|
* A text matcher that does regular expression matching.
|
||||||
*/
|
*/
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
<Layout>
|
<Layout>
|
||||||
<DimensionLayout dim="0">
|
<DimensionLayout dim="0">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Component id="jScrollPane1" alignment="0" max="32767" attributes="0"/>
|
<Component id="jScrollPane1" alignment="0" pref="800" max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
<DimensionLayout dim="1">
|
<DimensionLayout dim="1">
|
||||||
@ -173,7 +173,7 @@
|
|||||||
<Component id="deleteRuleButton" min="-2" max="-2" attributes="0"/>
|
<Component id="deleteRuleButton" min="-2" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
<EmptySpace min="24" pref="47" max="32767" attributes="0"/>
|
<EmptySpace min="24" max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
|
@ -960,7 +960,7 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
|
|||||||
.addComponent(editRuleButton)
|
.addComponent(editRuleButton)
|
||||||
.addGap(18, 18, 18)
|
.addGap(18, 18, 18)
|
||||||
.addComponent(deleteRuleButton)))
|
.addComponent(deleteRuleButton)))
|
||||||
.addGap(24, 47, Short.MAX_VALUE))))
|
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
|
||||||
);
|
);
|
||||||
|
|
||||||
jPanel1Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {copySetButton, deleteSetButton, editSetButton, exportSetButton, importSetButton, newSetButton});
|
jPanel1Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {copySetButton, deleteSetButton, editSetButton, exportSetButton, importSetButton, newSetButton});
|
||||||
@ -1060,7 +1060,7 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
|
|||||||
this.setLayout(layout);
|
this.setLayout(layout);
|
||||||
layout.setHorizontalGroup(
|
layout.setHorizontalGroup(
|
||||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addComponent(jScrollPane1)
|
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 800, Short.MAX_VALUE)
|
||||||
);
|
);
|
||||||
layout.setVerticalGroup(
|
layout.setVerticalGroup(
|
||||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
@ -47,22 +47,23 @@
|
|||||||
</Group>
|
</Group>
|
||||||
<Group type="102" attributes="0">
|
<Group type="102" attributes="0">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Component id="ruleNameTextField" max="32767" attributes="0"/>
|
||||||
<Group type="102" attributes="0">
|
<Group type="102" attributes="0">
|
||||||
<Component id="daysIncludedTextField" min="-2" pref="69" max="-2" attributes="0"/>
|
<Component id="daysIncludedTextField" min="-2" pref="69" max="-2" attributes="0"/>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Component id="daysIncludedLabel" min="-2" max="-2" attributes="0"/>
|
<Component id="daysIncludedLabel" min="-2" max="-2" attributes="0"/>
|
||||||
</Group>
|
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||||
<Component id="ruleNameTextField" pref="249" max="32767" attributes="0"/>
|
|
||||||
<Group type="102" alignment="0" attributes="0">
|
|
||||||
<Component id="fullNameRadioButton" min="-2" max="-2" attributes="0"/>
|
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
|
||||||
<Component id="extensionRadioButton" min="-2" pref="98" max="-2" attributes="0"/>
|
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
|
||||||
<Component id="nameRegexCheckbox" min="-2" max="-2" attributes="0"/>
|
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
<EmptySpace min="-2" pref="1" max="-2" attributes="0"/>
|
<EmptySpace min="-2" pref="1" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
|
<Group type="102" alignment="0" attributes="0">
|
||||||
|
<Component id="fullNameRadioButton" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="extensionRadioButton" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="nameRegexCheckbox" min="-2" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
<Component id="jLabel5" min="-2" max="-2" attributes="0"/>
|
<Component id="jLabel5" min="-2" max="-2" attributes="0"/>
|
||||||
@ -205,6 +206,9 @@
|
|||||||
</Property>
|
</Property>
|
||||||
<Property name="enabled" type="boolean" value="false"/>
|
<Property name="enabled" type="boolean" value="false"/>
|
||||||
</Properties>
|
</Properties>
|
||||||
|
<Events>
|
||||||
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="fullNameRadioButtonActionPerformed"/>
|
||||||
|
</Events>
|
||||||
</Component>
|
</Component>
|
||||||
<Component class="javax.swing.JRadioButton" name="extensionRadioButton">
|
<Component class="javax.swing.JRadioButton" name="extensionRadioButton">
|
||||||
<Properties>
|
<Properties>
|
||||||
@ -216,6 +220,9 @@
|
|||||||
</Property>
|
</Property>
|
||||||
<Property name="enabled" type="boolean" value="false"/>
|
<Property name="enabled" type="boolean" value="false"/>
|
||||||
</Properties>
|
</Properties>
|
||||||
|
<Events>
|
||||||
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="extensionRadioButtonActionPerformed"/>
|
||||||
|
</Events>
|
||||||
</Component>
|
</Component>
|
||||||
<Component class="javax.swing.JCheckBox" name="nameRegexCheckbox">
|
<Component class="javax.swing.JCheckBox" name="nameRegexCheckbox">
|
||||||
<Properties>
|
<Properties>
|
||||||
|
@ -18,7 +18,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.modules.interestingitems;
|
package org.sleuthkit.autopsy.modules.interestingitems;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@ -31,6 +33,7 @@ import org.openide.DialogDisplayer;
|
|||||||
import org.openide.NotifyDescriptor;
|
import org.openide.NotifyDescriptor;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.openide.util.NbBundle.Messages;
|
import org.openide.util.NbBundle.Messages;
|
||||||
|
import org.sleuthkit.autopsy.corecomponents.TextPrompt;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector;
|
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector;
|
||||||
import org.sleuthkit.autopsy.modules.interestingitems.FilesSetDefsPanel.PANEL_TYPE;
|
import org.sleuthkit.autopsy.modules.interestingitems.FilesSetDefsPanel.PANEL_TYPE;
|
||||||
@ -46,6 +49,8 @@ final class FilesSetRulePanel extends javax.swing.JPanel {
|
|||||||
"FilesSetRulePanel.kiloBytes=Kilobytes",
|
"FilesSetRulePanel.kiloBytes=Kilobytes",
|
||||||
"FilesSetRulePanel.megaBytes=Megabytes",
|
"FilesSetRulePanel.megaBytes=Megabytes",
|
||||||
"FilesSetRulePanel.gigaBytes=Gigabytes",
|
"FilesSetRulePanel.gigaBytes=Gigabytes",
|
||||||
|
"FilesSetRulePanel.nameTextField.fullNameExample=Example: \"file.exe\"",
|
||||||
|
"FilesSetRulePanel.nameTextField.extensionExample=Examples: \"jpg\" or \"jpg,jpeg,gif\"",
|
||||||
"FilesSetRulePanel.NoConditionError=Must have at least one condition to make a rule.",
|
"FilesSetRulePanel.NoConditionError=Must have at least one condition to make a rule.",
|
||||||
"FilesSetRulePanel.NoMimeTypeError=Please select a valid MIME type.",
|
"FilesSetRulePanel.NoMimeTypeError=Please select a valid MIME type.",
|
||||||
"FilesSetRulePanel.NoNameError=Name cannot be empty",
|
"FilesSetRulePanel.NoNameError=Name cannot be empty",
|
||||||
@ -62,6 +67,7 @@ final class FilesSetRulePanel extends javax.swing.JPanel {
|
|||||||
private static final List<String> ILLEGAL_FILE_PATH_CHARS = FilesSetsManager.getIllegalFilePathChars();
|
private static final List<String> ILLEGAL_FILE_PATH_CHARS = FilesSetsManager.getIllegalFilePathChars();
|
||||||
private JButton okButton;
|
private JButton okButton;
|
||||||
private JButton cancelButton;
|
private JButton cancelButton;
|
||||||
|
private TextPrompt nameTextFieldPrompt;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a files set rule panel in create rule mode.
|
* Constructs a files set rule panel in create rule mode.
|
||||||
@ -87,6 +93,8 @@ final class FilesSetRulePanel extends javax.swing.JPanel {
|
|||||||
this.dateCheckActionPerformed(null);
|
this.dateCheckActionPerformed(null);
|
||||||
populateComponentsWithDefaultValues();
|
populateComponentsWithDefaultValues();
|
||||||
this.setButtons(okButton, cancelButton);
|
this.setButtons(okButton, cancelButton);
|
||||||
|
|
||||||
|
updateNameTextFieldPrompt();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -120,6 +128,34 @@ final class FilesSetRulePanel extends javax.swing.JPanel {
|
|||||||
populatePathConditionComponents(rule);
|
populatePathConditionComponents(rule);
|
||||||
populateDateConditionComponents(rule);
|
populateDateConditionComponents(rule);
|
||||||
this.setButtons(okButton, cancelButton);
|
this.setButtons(okButton, cancelButton);
|
||||||
|
|
||||||
|
updateNameTextFieldPrompt();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the text prompt of the name text field based on the input type
|
||||||
|
* selection.
|
||||||
|
*/
|
||||||
|
private void updateNameTextFieldPrompt() {
|
||||||
|
/**
|
||||||
|
* Add text prompt to the text field.
|
||||||
|
*/
|
||||||
|
String text;
|
||||||
|
if (fullNameRadioButton.isSelected()) {
|
||||||
|
text = Bundle.FilesSetRulePanel_nameTextField_fullNameExample();
|
||||||
|
} else {
|
||||||
|
text = Bundle.FilesSetRulePanel_nameTextField_extensionExample();
|
||||||
|
}
|
||||||
|
nameTextFieldPrompt = new TextPrompt(text, nameTextField);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the foreground color and transparency of the text prompt.
|
||||||
|
*/
|
||||||
|
nameTextFieldPrompt.setForeground(Color.LIGHT_GRAY);
|
||||||
|
nameTextFieldPrompt.changeAlpha(0.9f); // Mostly opaque
|
||||||
|
|
||||||
|
validate();
|
||||||
|
repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -435,7 +471,7 @@ final class FilesSetRulePanel extends javax.swing.JPanel {
|
|||||||
if (!this.nameTextField.getText().isEmpty()) {
|
if (!this.nameTextField.getText().isEmpty()) {
|
||||||
if (this.nameRegexCheckbox.isSelected()) {
|
if (this.nameRegexCheckbox.isSelected()) {
|
||||||
try {
|
try {
|
||||||
Pattern pattern = Pattern.compile(this.nameTextField.getText());
|
Pattern pattern = Pattern.compile(this.nameTextField.getText(), Pattern.CASE_INSENSITIVE);
|
||||||
if (this.fullNameRadioButton.isSelected()) {
|
if (this.fullNameRadioButton.isSelected()) {
|
||||||
condition = new FilesSet.Rule.FullNameCondition(pattern);
|
condition = new FilesSet.Rule.FullNameCondition(pattern);
|
||||||
} else {
|
} else {
|
||||||
@ -449,7 +485,7 @@ final class FilesSetRulePanel extends javax.swing.JPanel {
|
|||||||
if (this.fullNameRadioButton.isSelected()) {
|
if (this.fullNameRadioButton.isSelected()) {
|
||||||
condition = new FilesSet.Rule.FullNameCondition(this.nameTextField.getText());
|
condition = new FilesSet.Rule.FullNameCondition(this.nameTextField.getText());
|
||||||
} else {
|
} else {
|
||||||
condition = new FilesSet.Rule.ExtensionCondition(this.nameTextField.getText());
|
condition = new FilesSet.Rule.ExtensionCondition(Arrays.asList(this.nameTextField.getText().split(",")));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.log(Level.SEVERE, "Attempt to get name condition with illegal chars"); // NON-NLS
|
logger.log(Level.SEVERE, "Attempt to get name condition with illegal chars"); // NON-NLS
|
||||||
@ -520,7 +556,7 @@ final class FilesSetRulePanel extends javax.swing.JPanel {
|
|||||||
if (!this.pathTextField.getText().isEmpty()) {
|
if (!this.pathTextField.getText().isEmpty()) {
|
||||||
if (this.pathRegexCheckBox.isSelected()) {
|
if (this.pathRegexCheckBox.isSelected()) {
|
||||||
try {
|
try {
|
||||||
condition = new FilesSet.Rule.ParentPathCondition(Pattern.compile(this.pathTextField.getText()));
|
condition = new FilesSet.Rule.ParentPathCondition(Pattern.compile(this.pathTextField.getText(), Pattern.CASE_INSENSITIVE));
|
||||||
} catch (PatternSyntaxException ex) {
|
} catch (PatternSyntaxException ex) {
|
||||||
logger.log(Level.SEVERE, "Attempt to get malformed path condition", ex); // NON-NLS
|
logger.log(Level.SEVERE, "Attempt to get malformed path condition", ex); // NON-NLS
|
||||||
throw new IllegalStateException("The files set rule panel path condition is not in a valid state"); // NON-NLS
|
throw new IllegalStateException("The files set rule panel path condition is not in a valid state"); // NON-NLS
|
||||||
@ -657,10 +693,20 @@ final class FilesSetRulePanel extends javax.swing.JPanel {
|
|||||||
nameButtonGroup.add(fullNameRadioButton);
|
nameButtonGroup.add(fullNameRadioButton);
|
||||||
org.openide.awt.Mnemonics.setLocalizedText(fullNameRadioButton, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.fullNameRadioButton.text")); // NOI18N
|
org.openide.awt.Mnemonics.setLocalizedText(fullNameRadioButton, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.fullNameRadioButton.text")); // NOI18N
|
||||||
fullNameRadioButton.setEnabled(false);
|
fullNameRadioButton.setEnabled(false);
|
||||||
|
fullNameRadioButton.addActionListener(new java.awt.event.ActionListener() {
|
||||||
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
|
fullNameRadioButtonActionPerformed(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
nameButtonGroup.add(extensionRadioButton);
|
nameButtonGroup.add(extensionRadioButton);
|
||||||
org.openide.awt.Mnemonics.setLocalizedText(extensionRadioButton, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.extensionRadioButton.text")); // NOI18N
|
org.openide.awt.Mnemonics.setLocalizedText(extensionRadioButton, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.extensionRadioButton.text")); // NOI18N
|
||||||
extensionRadioButton.setEnabled(false);
|
extensionRadioButton.setEnabled(false);
|
||||||
|
extensionRadioButton.addActionListener(new java.awt.event.ActionListener() {
|
||||||
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
|
extensionRadioButtonActionPerformed(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
org.openide.awt.Mnemonics.setLocalizedText(nameRegexCheckbox, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.nameRegexCheckbox.text")); // NOI18N
|
org.openide.awt.Mnemonics.setLocalizedText(nameRegexCheckbox, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.nameRegexCheckbox.text")); // NOI18N
|
||||||
nameRegexCheckbox.setEnabled(false);
|
nameRegexCheckbox.setEnabled(false);
|
||||||
@ -782,18 +828,19 @@ final class FilesSetRulePanel extends javax.swing.JPanel {
|
|||||||
.addComponent(pathSeparatorInfoLabel))
|
.addComponent(pathSeparatorInfoLabel))
|
||||||
.addGroup(layout.createSequentialGroup()
|
.addGroup(layout.createSequentialGroup()
|
||||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addComponent(ruleNameTextField)
|
||||||
.addGroup(layout.createSequentialGroup()
|
.addGroup(layout.createSequentialGroup()
|
||||||
.addComponent(daysIncludedTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 69, javax.swing.GroupLayout.PREFERRED_SIZE)
|
.addComponent(daysIncludedTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 69, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(daysIncludedLabel))
|
.addComponent(daysIncludedLabel)
|
||||||
.addComponent(ruleNameTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 249, Short.MAX_VALUE)
|
.addGap(0, 0, Short.MAX_VALUE)))
|
||||||
|
.addGap(1, 1, 1))
|
||||||
.addGroup(layout.createSequentialGroup()
|
.addGroup(layout.createSequentialGroup()
|
||||||
.addComponent(fullNameRadioButton)
|
.addComponent(fullNameRadioButton)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(extensionRadioButton, javax.swing.GroupLayout.PREFERRED_SIZE, 98, javax.swing.GroupLayout.PREFERRED_SIZE)
|
.addComponent(extensionRadioButton)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(nameRegexCheckbox)))
|
.addComponent(nameRegexCheckbox))))
|
||||||
.addGap(1, 1, 1))))
|
|
||||||
.addComponent(jLabel5)
|
.addComponent(jLabel5)
|
||||||
.addGroup(layout.createSequentialGroup()
|
.addGroup(layout.createSequentialGroup()
|
||||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
@ -952,6 +999,14 @@ final class FilesSetRulePanel extends javax.swing.JPanel {
|
|||||||
this.setOkButton();
|
this.setOkButton();
|
||||||
}//GEN-LAST:event_mimeCheckActionPerformed
|
}//GEN-LAST:event_mimeCheckActionPerformed
|
||||||
|
|
||||||
|
private void extensionRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_extensionRadioButtonActionPerformed
|
||||||
|
updateNameTextFieldPrompt();
|
||||||
|
}//GEN-LAST:event_extensionRadioButtonActionPerformed
|
||||||
|
|
||||||
|
private void fullNameRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fullNameRadioButtonActionPerformed
|
||||||
|
updateNameTextFieldPrompt();
|
||||||
|
}//GEN-LAST:event_fullNameRadioButtonActionPerformed
|
||||||
|
|
||||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
private javax.swing.JRadioButton allRadioButton;
|
private javax.swing.JRadioButton allRadioButton;
|
||||||
private javax.swing.JCheckBox dateCheck;
|
private javax.swing.JCheckBox dateCheck;
|
||||||
|
@ -25,6 +25,7 @@ import java.io.IOException;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -280,7 +281,7 @@ class InterestingItemsFilesSetSettings implements Serializable {
|
|||||||
if (elem.getTagName().equals(NAME_RULE_TAG)) {
|
if (elem.getTagName().equals(NAME_RULE_TAG)) {
|
||||||
nameCondition = new FilesSet.Rule.FullNameCondition(content);
|
nameCondition = new FilesSet.Rule.FullNameCondition(content);
|
||||||
} else if (elem.getTagName().equals(EXTENSION_RULE_TAG)) {
|
} else if (elem.getTagName().equals(EXTENSION_RULE_TAG)) {
|
||||||
nameCondition = new FilesSet.Rule.ExtensionCondition(content);
|
nameCondition = new FilesSet.Rule.ExtensionCondition(Arrays.asList(content.split(",")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
|||||||
import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor;
|
import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor;
|
||||||
import org.sleuthkit.autopsy.coreutils.TimeStampUtils;
|
import org.sleuthkit.autopsy.coreutils.TimeStampUtils;
|
||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
|
import org.sleuthkit.datamodel.DataSource;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A runnable that adds an archive data source as well as data sources contained
|
* A runnable that adds an archive data source as well as data sources contained
|
||||||
@ -195,10 +196,19 @@ class AddArchiveTask implements Runnable {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we are here it means the data source was addedd successfully
|
// if we are here it means the data source was added successfully
|
||||||
success = true;
|
success = true;
|
||||||
newDataSources.addAll(internalDataSource.getContent());
|
newDataSources.addAll(internalDataSource.getContent());
|
||||||
|
|
||||||
|
// Update the names for all new data sources to be the root archive plus the name of the data source
|
||||||
|
for (Content c:internalDataSource.getContent()) {
|
||||||
|
if (c instanceof DataSource) {
|
||||||
|
DataSource ds = (DataSource) c;
|
||||||
|
String newName = Paths.get(archivePath).getFileName() + "/" + ds.getName();
|
||||||
|
ds.setDisplayName(newName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// skip all other DSPs for this data source
|
// skip all other DSPs for this data source
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,7 @@ import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
|
|||||||
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException;
|
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.coreutils.NetworkUtils;
|
import org.sleuthkit.autopsy.coreutils.NetworkUtils;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.StopWatch;
|
||||||
import org.sleuthkit.autopsy.events.AutopsyEventException;
|
import org.sleuthkit.autopsy.events.AutopsyEventException;
|
||||||
import org.sleuthkit.autopsy.events.AutopsyEventPublisher;
|
import org.sleuthkit.autopsy.events.AutopsyEventPublisher;
|
||||||
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJob.ProcessingStatus;
|
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJob.ProcessingStatus;
|
||||||
@ -666,43 +667,73 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen
|
|||||||
* @return A result code indicating success, partial success, or failure.
|
* @return A result code indicating success, partial success, or failure.
|
||||||
*/
|
*/
|
||||||
CaseDeletionResult deleteCase(AutoIngestJob job) {
|
CaseDeletionResult deleteCase(AutoIngestJob job) {
|
||||||
synchronized (jobsLock) {
|
|
||||||
String caseName = job.getManifest().getCaseName();
|
String caseName = job.getManifest().getCaseName();
|
||||||
Path metadataFilePath = job.getCaseDirectoryPath().resolve(caseName + CaseMetadata.getFileExtension());
|
Path caseDirectoryPath = job.getCaseDirectoryPath();
|
||||||
|
Path metadataFilePath = caseDirectoryPath.resolve(caseName + CaseMetadata.getFileExtension());
|
||||||
|
StopWatch stopWatch = new StopWatch();
|
||||||
|
stopWatch.start();
|
||||||
|
synchronized (jobsLock) {
|
||||||
|
stopWatch.stop();
|
||||||
|
LOGGER.log(Level.INFO, String.format("Used %d s to acquire jobsLock (Java monitor in AutoIngestMonitor class) for case %s at %s", stopWatch.getElapsedTimeSecs(), caseName, caseDirectoryPath));
|
||||||
|
stopWatch.reset();
|
||||||
|
stopWatch.start();
|
||||||
try {
|
try {
|
||||||
CaseMetadata metadata = new CaseMetadata(metadataFilePath);
|
CaseMetadata metadata = new CaseMetadata(metadataFilePath);
|
||||||
|
stopWatch.stop();
|
||||||
|
LOGGER.log(Level.INFO, String.format("Used %d s to read case metadata for case %s at %s", stopWatch.getElapsedTimeSecs(), caseName, caseDirectoryPath));
|
||||||
|
stopWatch.reset();
|
||||||
|
stopWatch.start();
|
||||||
Case.deleteCase(metadata);
|
Case.deleteCase(metadata);
|
||||||
|
|
||||||
} catch (CaseMetadata.CaseMetadataException ex) {
|
} catch (CaseMetadata.CaseMetadataException ex) {
|
||||||
LOGGER.log(Level.SEVERE, String.format("Failed to get case metadata file %s for case %s at %s", metadataFilePath.toString(), caseName, job.getCaseDirectoryPath().toString()), ex);
|
LOGGER.log(Level.SEVERE, String.format("Failed to read case metadata file %s for case %s at %s", metadataFilePath, caseName, caseDirectoryPath), ex);
|
||||||
|
stopWatch.stop();
|
||||||
|
LOGGER.log(Level.INFO, String.format("Used %d s to fail to read case metadata file %s for case %s at %s", stopWatch.getElapsedTimeSecs(), metadataFilePath, caseName, caseDirectoryPath));
|
||||||
return CaseDeletionResult.FAILED;
|
return CaseDeletionResult.FAILED;
|
||||||
} catch (CaseActionException ex) {
|
} catch (CaseActionException ex) {
|
||||||
LOGGER.log(Level.SEVERE, String.format("Failed to physically delete case %s at %s", caseName, job.getCaseDirectoryPath().toString()), ex);
|
LOGGER.log(Level.SEVERE, String.format("Failed to delete case %s at %s", caseName, caseDirectoryPath), ex);
|
||||||
return CaseDeletionResult.FAILED;
|
return CaseDeletionResult.FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the state of completed jobs associated with this case to indicate
|
// Update the state of completed jobs associated with this case to indicate
|
||||||
// that the case has been deleted
|
// that the case has been deleted
|
||||||
for (AutoIngestJob completedJob : getCompletedJobs()) {
|
stopWatch.reset();
|
||||||
|
stopWatch.start();
|
||||||
|
List<AutoIngestJob> completedJobs = getCompletedJobs();
|
||||||
|
stopWatch.stop();
|
||||||
|
LOGGER.log(Level.INFO, String.format("Used %d s to get completed jobs listing for case %s at %s", stopWatch.getElapsedTimeSecs(), caseName, caseDirectoryPath));
|
||||||
|
stopWatch.reset();
|
||||||
|
stopWatch.start();
|
||||||
|
for (AutoIngestJob completedJob : completedJobs) {
|
||||||
if (caseName.equals(completedJob.getManifest().getCaseName())) {
|
if (caseName.equals(completedJob.getManifest().getCaseName())) {
|
||||||
try {
|
try {
|
||||||
completedJob.setProcessingStatus(DELETED);
|
completedJob.setProcessingStatus(DELETED);
|
||||||
AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(completedJob);
|
AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(completedJob);
|
||||||
coordinationService.setNodeData(CoordinationService.CategoryNode.MANIFESTS, completedJob.getManifest().getFilePath().toString(), nodeData.toArray());
|
coordinationService.setNodeData(CoordinationService.CategoryNode.MANIFESTS, completedJob.getManifest().getFilePath().toString(), nodeData.toArray());
|
||||||
} catch (CoordinationServiceException | InterruptedException ex) {
|
} catch (CoordinationServiceException | InterruptedException ex) {
|
||||||
LOGGER.log(Level.SEVERE, String.format("Failed to update completed job node data for %s when deleting case %s", completedJob.getManifest().getFilePath().toString(), caseName), ex);
|
LOGGER.log(Level.SEVERE, String.format("Failed to update completed job node data for %s when deleting case %s at %s", completedJob.getManifest().getFilePath(), caseName, caseDirectoryPath), ex);
|
||||||
|
stopWatch.stop();
|
||||||
|
LOGGER.log(Level.INFO, String.format("Used %d s to fail to update job node data for completed jobs for case %s at %s", stopWatch.getElapsedTimeSecs(), caseName, caseDirectoryPath));
|
||||||
return CaseDeletionResult.PARTIALLY_DELETED;
|
return CaseDeletionResult.PARTIALLY_DELETED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
stopWatch.stop();
|
||||||
|
LOGGER.log(Level.INFO, String.format("Used %d s to update job node data for completed jobs for case %s at %s", stopWatch.getElapsedTimeSecs(), caseName, caseDirectoryPath));
|
||||||
|
|
||||||
// Remove jobs associated with this case from the completed jobs collection.
|
// Remove jobs associated with this case from the completed jobs collection.
|
||||||
jobsSnapshot.completedJobs.removeIf((AutoIngestJob completedJob)
|
stopWatch.reset();
|
||||||
|
stopWatch.start();
|
||||||
|
completedJobs.removeIf((AutoIngestJob completedJob)
|
||||||
-> completedJob.getManifest().getCaseName().equals(caseName));
|
-> completedJob.getManifest().getCaseName().equals(caseName));
|
||||||
|
stopWatch.stop();
|
||||||
|
LOGGER.log(Level.INFO, String.format("Used %d s to remove completed jobs for case %s at %s from current jobs snapshot", stopWatch.getElapsedTimeSecs(), caseName, caseDirectoryPath));
|
||||||
|
|
||||||
// Publish a message to update auto ingest nodes.
|
// Publish a message to update auto ingest nodes.
|
||||||
|
stopWatch.reset();
|
||||||
|
stopWatch.start();
|
||||||
eventPublisher.publishRemotely(new AutoIngestCaseDeletedEvent(caseName, LOCAL_HOST_NAME, AutoIngestManager.getSystemUserNameProperty()));
|
eventPublisher.publishRemotely(new AutoIngestCaseDeletedEvent(caseName, LOCAL_HOST_NAME, AutoIngestManager.getSystemUserNameProperty()));
|
||||||
|
stopWatch.stop();
|
||||||
|
LOGGER.log(Level.INFO, String.format("Used %d s to publish job deletion event for case %s at %s", stopWatch.getElapsedTimeSecs(), caseName,caseDirectoryPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
return CaseDeletionResult.FULLY_DELETED;
|
return CaseDeletionResult.FULLY_DELETED;
|
||||||
|
@ -25,9 +25,7 @@ import java.util.Calendar;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.SimpleTimeZone;
|
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
import java.util.TimeZone;
|
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
import javax.swing.JFileChooser;
|
import javax.swing.JFileChooser;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
@ -43,6 +41,7 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
|||||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
||||||
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
|
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
|
||||||
import org.sleuthkit.autopsy.coreutils.PathValidator;
|
import org.sleuthkit.autopsy.coreutils.PathValidator;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.TimeZoneUtils;
|
||||||
|
|
||||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
final class MemoryDSInputPanel extends JPanel implements DocumentListener {
|
final class MemoryDSInputPanel extends JPanel implements DocumentListener {
|
||||||
@ -132,26 +131,13 @@ final class MemoryDSInputPanel extends JPanel implements DocumentListener {
|
|||||||
* machine time zone to be selected.
|
* machine time zone to be selected.
|
||||||
*/
|
*/
|
||||||
private void createTimeZoneList() {
|
private void createTimeZoneList() {
|
||||||
// load and add all timezone
|
List<String> timeZoneList = TimeZoneUtils.createTimeZoneList();
|
||||||
String[] ids = SimpleTimeZone.getAvailableIDs();
|
for (String timeZone : timeZoneList) {
|
||||||
for (String id : ids) {
|
timeZoneComboBox.addItem(timeZone);
|
||||||
TimeZone zone = TimeZone.getTimeZone(id);
|
|
||||||
int offset = zone.getRawOffset() / 1000;
|
|
||||||
int hour = offset / 3600;
|
|
||||||
int minutes = (offset % 3600) / 60;
|
|
||||||
String item = String.format("(GMT%+d:%02d) %s", hour, minutes, id);
|
|
||||||
|
|
||||||
timeZoneComboBox.addItem(item);
|
|
||||||
}
|
}
|
||||||
// get the current timezone
|
|
||||||
TimeZone thisTimeZone = Calendar.getInstance().getTimeZone();
|
|
||||||
int thisOffset = thisTimeZone.getRawOffset() / 1000;
|
|
||||||
int thisHour = thisOffset / 3600;
|
|
||||||
int thisMinutes = (thisOffset % 3600) / 60;
|
|
||||||
String formatted = String.format("(GMT%+d:%02d) %s", thisHour, thisMinutes, thisTimeZone.getID());
|
|
||||||
|
|
||||||
// set the selected timezone
|
// set the selected timezone
|
||||||
timeZoneComboBox.setSelectedItem(formatted);
|
timeZoneComboBox.setSelectedItem(TimeZoneUtils.createTimeZoneString(Calendar.getInstance().getTimeZone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
Manifest-Version: 1.0
|
Manifest-Version: 1.0
|
||||||
OpenIDE-Module: org.sleuthkit.autopsy.imagegallery/2
|
OpenIDE-Module: org.sleuthkit.autopsy.imagegallery/2
|
||||||
OpenIDE-Module-Implementation-Version: 4
|
OpenIDE-Module-Implementation-Version: 5
|
||||||
OpenIDE-Module-Layer: org/sleuthkit/autopsy/imagegallery/layer.xml
|
OpenIDE-Module-Layer: org/sleuthkit/autopsy/imagegallery/layer.xml
|
||||||
OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/imagegallery/Bundle.properties
|
OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/imagegallery/Bundle.properties
|
||||||
|
|
||||||
|
@ -219,8 +219,13 @@ public enum FileTypeUtils {
|
|||||||
* type. False if a non image/video mimetype. empty Optional if a
|
* type. False if a non image/video mimetype. empty Optional if a
|
||||||
* mimetype could not be detected.
|
* mimetype could not be detected.
|
||||||
*/
|
*/
|
||||||
static boolean hasDrawableMIMEType(AbstractFile file) throws FileTypeDetector.FileTypeDetectorInitException {
|
static boolean hasDrawableMIMEType(AbstractFile file) {
|
||||||
String mimeType = getFileTypeDetector().getMIMEType(file).toLowerCase();
|
String mimeType = file.getMIMEType();
|
||||||
|
if (mimeType == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mimeType = mimeType.toLowerCase();
|
||||||
return isDrawableMimeType(mimeType) || (mimeType.equals("audio/x-aiff") && "tiff".equalsIgnoreCase(file.getNameExtension()));
|
return isDrawableMimeType(mimeType) || (mimeType.equals("audio/x-aiff") && "tiff".equalsIgnoreCase(file.getNameExtension()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,13 +239,13 @@ public enum FileTypeUtils {
|
|||||||
* available, a video extension.
|
* available, a video extension.
|
||||||
*/
|
*/
|
||||||
public static boolean hasVideoMIMEType(AbstractFile file) {
|
public static boolean hasVideoMIMEType(AbstractFile file) {
|
||||||
try {
|
String mimeType = file.getMIMEType();
|
||||||
String mimeType = getFileTypeDetector().getMIMEType(file).toLowerCase();
|
if (mimeType == null) {
|
||||||
return mimeType.startsWith("video/") || videoMimeTypes.contains(mimeType);
|
|
||||||
} catch (FileTypeDetector.FileTypeDetectorInitException ex) {
|
|
||||||
LOGGER.log(Level.SEVERE, "Error determining MIME type of " + getContentPathSafe(file), ex);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mimeType = mimeType.toLowerCase();
|
||||||
|
return mimeType.startsWith("video/") || videoMimeTypes.contains(mimeType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -67,7 +67,6 @@ import org.sleuthkit.autopsy.imagegallery.datamodel.HashSetManager;
|
|||||||
import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupManager;
|
import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupManager;
|
||||||
import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupViewState;
|
import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupViewState;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||||
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector;
|
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
import org.sleuthkit.datamodel.DataSource;
|
import org.sleuthkit.datamodel.DataSource;
|
||||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
@ -253,6 +252,7 @@ public final class ImageGalleryController {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Should the "forward" button on the history be enabled?
|
* Should the "forward" button on the history be enabled?
|
||||||
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public ReadOnlyBooleanProperty getCanAdvance() {
|
public ReadOnlyBooleanProperty getCanAdvance() {
|
||||||
@ -261,6 +261,7 @@ public final class ImageGalleryController {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Should the "Back" button on the history be enabled?
|
* Should the "Back" button on the history be enabled?
|
||||||
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public ReadOnlyBooleanProperty getCanRetreat() {
|
public ReadOnlyBooleanProperty getCanRetreat() {
|
||||||
@ -268,10 +269,9 @@ public final class ImageGalleryController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display the passed in group. Causes this group to
|
* Display the passed in group. Causes this group to get recorded in the
|
||||||
* get recorded in the history queue and observers of the
|
* history queue and observers of the current state will be notified and
|
||||||
* current state will be notified and update their panels/widgets
|
* update their panels/widgets appropriately.
|
||||||
* appropriately.
|
|
||||||
*
|
*
|
||||||
* @param newState
|
* @param newState
|
||||||
*/
|
*/
|
||||||
@ -282,6 +282,7 @@ public final class ImageGalleryController {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Display the next group in the "forward" history stack
|
* Display the next group in the "forward" history stack
|
||||||
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public GroupViewState advance() {
|
public GroupViewState advance() {
|
||||||
@ -290,6 +291,7 @@ public final class ImageGalleryController {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Display the previous group in the "back" history stack
|
* Display the previous group in the "back" history stack
|
||||||
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public GroupViewState retreat() {
|
public GroupViewState retreat() {
|
||||||
@ -433,10 +435,6 @@ public final class ImageGalleryController {
|
|||||||
return drawableDB.getFileFromID(fileID);
|
return drawableDB.getFileFromID(fileID);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReadOnlyDoubleProperty regroupProgress() {
|
|
||||||
return groupManager.regroupProgress();
|
|
||||||
}
|
|
||||||
|
|
||||||
public HashSetManager getHashSetManager() {
|
public HashSetManager getHashSetManager() {
|
||||||
return hashSetManager;
|
return hashSetManager;
|
||||||
}
|
}
|
||||||
@ -696,8 +694,17 @@ public final class ImageGalleryController {
|
|||||||
// Cycle through all of the files returned and call processFile on each
|
// Cycle through all of the files returned and call processFile on each
|
||||||
//do in transaction
|
//do in transaction
|
||||||
drawableDbTransaction = taskDB.beginTransaction();
|
drawableDbTransaction = taskDB.beginTransaction();
|
||||||
caseDbTransaction = tskCase.beginTransaction();
|
|
||||||
|
/* We are going to periodically commit the CaseDB transaction
|
||||||
|
* and sleep so that the user can have Autopsy do other stuff
|
||||||
|
* while these bulk tasks are ongoing.
|
||||||
|
*/
|
||||||
|
int caseDbCounter = 0;
|
||||||
for (final AbstractFile f : files) {
|
for (final AbstractFile f : files) {
|
||||||
|
if (caseDbTransaction == null) {
|
||||||
|
caseDbTransaction = tskCase.beginTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
if (isCancelled() || Thread.interrupted()) {
|
if (isCancelled() || Thread.interrupted()) {
|
||||||
logger.log(Level.WARNING, "Task cancelled or interrupted: not all contents may be transfered to drawable database."); //NON-NLS
|
logger.log(Level.WARNING, "Task cancelled or interrupted: not all contents may be transfered to drawable database."); //NON-NLS
|
||||||
taskCompletionStatus = false;
|
taskCompletionStatus = false;
|
||||||
@ -712,6 +719,14 @@ public final class ImageGalleryController {
|
|||||||
progressHandle.progress(f.getName(), workDone);
|
progressHandle.progress(f.getName(), workDone);
|
||||||
updateProgress(workDone - 1 / (double) files.size());
|
updateProgress(workDone - 1 / (double) files.size());
|
||||||
updateMessage(f.getName());
|
updateMessage(f.getName());
|
||||||
|
|
||||||
|
// Periodically, commit the transaction (which frees the lock) and sleep
|
||||||
|
// to allow other threads to get some work done in CaseDB
|
||||||
|
if ((++caseDbCounter % 200) == 0) {
|
||||||
|
caseDbTransaction.commit();
|
||||||
|
caseDbTransaction = null;
|
||||||
|
Thread.sleep(500); // 1/2 second
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
progressHandle.finish();
|
progressHandle.finish();
|
||||||
@ -720,13 +735,16 @@ public final class ImageGalleryController {
|
|||||||
updateProgress(1.0);
|
updateProgress(1.0);
|
||||||
|
|
||||||
progressHandle.start();
|
progressHandle.start();
|
||||||
|
if (caseDbTransaction != null) {
|
||||||
caseDbTransaction.commit();
|
caseDbTransaction.commit();
|
||||||
caseDbTransaction = null;
|
caseDbTransaction = null;
|
||||||
|
}
|
||||||
|
|
||||||
// pass true so that groupmanager is notified of the changes
|
// pass true so that groupmanager is notified of the changes
|
||||||
taskDB.commitTransaction(drawableDbTransaction, true);
|
taskDB.commitTransaction(drawableDbTransaction, true);
|
||||||
drawableDbTransaction = null;
|
drawableDbTransaction = null;
|
||||||
|
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException | InterruptedException ex) {
|
||||||
progressHandle.progress(Bundle.BulkTask_stopCopy_status());
|
progressHandle.progress(Bundle.BulkTask_stopCopy_status());
|
||||||
logger.log(Level.WARNING, "Stopping copy to drawable db task. Failed to transfer all database contents", ex); //NON-NLS
|
logger.log(Level.WARNING, "Stopping copy to drawable db task. Failed to transfer all database contents", ex); //NON-NLS
|
||||||
MessageNotifyUtil.Notify.warn(Bundle.BulkTask_errPopulating_errMsg(), ex.getMessage());
|
MessageNotifyUtil.Notify.warn(Bundle.BulkTask_errPopulating_errMsg(), ex.getMessage());
|
||||||
@ -792,7 +810,6 @@ public final class ImageGalleryController {
|
|||||||
if (known) {
|
if (known) {
|
||||||
taskDB.removeFile(f.getId(), tr); //remove known files
|
taskDB.removeFile(f.getId(), tr); //remove known files
|
||||||
} else {
|
} else {
|
||||||
try {
|
|
||||||
// if mimetype of the file hasn't been ascertained, ingest might not have completed yet.
|
// if mimetype of the file hasn't been ascertained, ingest might not have completed yet.
|
||||||
if (null == f.getMIMEType()) {
|
if (null == f.getMIMEType()) {
|
||||||
// set to false to force the DB to be marked as stale
|
// set to false to force the DB to be marked as stale
|
||||||
@ -804,9 +821,6 @@ public final class ImageGalleryController {
|
|||||||
else {
|
else {
|
||||||
taskDB.removeFile(f.getId(), tr);
|
taskDB.removeFile(f.getId(), tr);
|
||||||
}
|
}
|
||||||
} catch (FileTypeDetector.FileTypeDetectorInitException ex) {
|
|
||||||
throw new TskCoreException("Failed to initialize FileTypeDetector.", ex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -840,7 +854,7 @@ public final class ImageGalleryController {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
void processFile(final AbstractFile f, DrawableDB.DrawableTransaction tr, CaseDbTransaction caseDBTransaction) {
|
void processFile(final AbstractFile f, DrawableDB.DrawableTransaction tr, CaseDbTransaction caseDBTransaction) {
|
||||||
taskDB.insertFile(DrawableFile.create(f, false, false), tr, caseDBTransaction);
|
taskDB.insertBasicFileData(DrawableFile.create(f, false, false), tr, caseDBTransaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -208,7 +208,7 @@ public class ImageGalleryModule {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (IngestManager.IngestModuleEvent.valueOf(evt.getPropertyName()) == DATA_ADDED) {
|
else if (IngestManager.IngestModuleEvent.valueOf(evt.getPropertyName()) == DATA_ADDED) {
|
||||||
ModuleDataEvent mde = (ModuleDataEvent)evt.getOldValue();
|
ModuleDataEvent mde = (ModuleDataEvent) evt.getOldValue();
|
||||||
|
|
||||||
if (mde.getBlackboardArtifactType().getTypeID() == ARTIFACT_TYPE.TSK_METADATA_EXIF.getTypeID()) {
|
if (mde.getBlackboardArtifactType().getTypeID() == ARTIFACT_TYPE.TSK_METADATA_EXIF.getTypeID()) {
|
||||||
DrawableDB drawableDB = controller.getDatabase();
|
DrawableDB drawableDB = controller.getDatabase();
|
||||||
@ -336,8 +336,9 @@ public class ImageGalleryModule {
|
|||||||
try {
|
try {
|
||||||
ImageGalleryController con = getController();
|
ImageGalleryController con = getController();
|
||||||
con.setStale(true);
|
con.setStale(true);
|
||||||
if (con.isListeningEnabled() && ImageGalleryTopComponent.isImageGalleryOpen()) {
|
if (con.isListeningEnabled()) {
|
||||||
SwingUtilities.invokeLater(() -> {
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
if (ImageGalleryTopComponent.isImageGalleryOpen()) {
|
||||||
int showAnswer = JOptionPane.showConfirmDialog(ImageGalleryTopComponent.getTopComponent(),
|
int showAnswer = JOptionPane.showConfirmDialog(ImageGalleryTopComponent.getTopComponent(),
|
||||||
Bundle.ImageGalleryController_dataSourceAnalyzed_confDlg_msg(),
|
Bundle.ImageGalleryController_dataSourceAnalyzed_confDlg_msg(),
|
||||||
Bundle.ImageGalleryController_dataSourceAnalyzed_confDlg_title(),
|
Bundle.ImageGalleryController_dataSourceAnalyzed_confDlg_title(),
|
||||||
@ -352,6 +353,7 @@ public class ImageGalleryModule {
|
|||||||
default:
|
default:
|
||||||
break; //do nothing
|
break; //do nothing
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (NoCurrentCaseException ex) {
|
} catch (NoCurrentCaseException ex) {
|
||||||
|
@ -698,8 +698,8 @@ public final class DrawableDB {
|
|||||||
// query to find the group id from attribute/value
|
// query to find the group id from attribute/value
|
||||||
return String.format(" SELECT group_id FROM " + GROUPS_TABLENAME
|
return String.format(" SELECT group_id FROM " + GROUPS_TABLENAME
|
||||||
+ " WHERE attribute = \'%s\' AND value = \'%s\' AND data_source_obj_id = %d",
|
+ " WHERE attribute = \'%s\' AND value = \'%s\' AND data_source_obj_id = %d",
|
||||||
groupKey.getAttribute().attrName.toString(),
|
SleuthkitCase.escapeSingleQuotes(groupKey.getAttribute().attrName.toString()),
|
||||||
groupKey.getValueDisplayName(),
|
SleuthkitCase.escapeSingleQuotes(groupKey.getValueDisplayName()),
|
||||||
(groupKey.getAttribute() == DrawableAttribute.PATH) ? groupKey.getDataSourceObjId() : 0);
|
(groupKey.getAttribute() == DrawableAttribute.PATH) ? groupKey.getDataSourceObjId() : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -776,8 +776,8 @@ public final class DrawableDB {
|
|||||||
// query to find the group id from attribute/value
|
// query to find the group id from attribute/value
|
||||||
String innerQuery = String.format("( SELECT group_id FROM " + GROUPS_TABLENAME
|
String innerQuery = String.format("( SELECT group_id FROM " + GROUPS_TABLENAME
|
||||||
+ " WHERE attribute = \'%s\' AND value = \'%s\' and data_source_obj_id = %d )",
|
+ " WHERE attribute = \'%s\' AND value = \'%s\' and data_source_obj_id = %d )",
|
||||||
groupKey.getAttribute().attrName.toString(),
|
SleuthkitCase.escapeSingleQuotes(groupKey.getAttribute().attrName.toString()),
|
||||||
groupKey.getValueDisplayName(),
|
SleuthkitCase.escapeSingleQuotes(groupKey.getValueDisplayName()),
|
||||||
groupKey.getAttribute() == DrawableAttribute.PATH ? groupKey.getDataSourceObjId() : 0);
|
groupKey.getAttribute() == DrawableAttribute.PATH ? groupKey.getDataSourceObjId() : 0);
|
||||||
|
|
||||||
String insertSQL = String.format(" (group_id, examiner_id, seen) VALUES (%s, %d, %d)", innerQuery, examinerID, seen ? 1 : 0);
|
String insertSQL = String.format(" (group_id, examiner_id, seen) VALUES (%s, %d, %d)", innerQuery, examinerID, seen ? 1 : 0);
|
||||||
@ -828,12 +828,26 @@ public final class DrawableDB {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void insertFile(DrawableFile f, DrawableTransaction tr, CaseDbTransaction caseDbTransaction) {
|
/**
|
||||||
insertOrUpdateFile(f, tr, insertFileStmt, caseDbTransaction);
|
* Insert basic file data (no groups) into the DB during pre-population phase
|
||||||
|
* @param f
|
||||||
|
* @param tr
|
||||||
|
* @param caseDbTransaction
|
||||||
|
*/
|
||||||
|
public void insertBasicFileData(DrawableFile f, DrawableTransaction tr, CaseDbTransaction caseDbTransaction) {
|
||||||
|
insertOrUpdateFile(f, tr, caseDbTransaction, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update an existing entry (or make a new one) into the DB that includes group information.
|
||||||
|
* Called when a file has been analyzed or during a bulk rebuild
|
||||||
|
*
|
||||||
|
* @param f
|
||||||
|
* @param tr
|
||||||
|
* @param caseDbTransaction
|
||||||
|
*/
|
||||||
public void updateFile(DrawableFile f, DrawableTransaction tr, CaseDbTransaction caseDbTransaction) {
|
public void updateFile(DrawableFile f, DrawableTransaction tr, CaseDbTransaction caseDbTransaction) {
|
||||||
insertOrUpdateFile(f, tr, updateFileStmt, caseDbTransaction);
|
insertOrUpdateFile(f, tr, caseDbTransaction, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -964,14 +978,24 @@ public final class DrawableDB {
|
|||||||
*
|
*
|
||||||
* @param f The file to insert.
|
* @param f The file to insert.
|
||||||
* @param tr a transaction to use, must not be null
|
* @param tr a transaction to use, must not be null
|
||||||
* @param stmt the statement that does the actual inserting
|
* @param caseDbTransaction
|
||||||
|
* @param addGroups True if groups for file should be inserted into db too
|
||||||
*/
|
*/
|
||||||
private void insertOrUpdateFile(DrawableFile f, @Nonnull DrawableTransaction tr, @Nonnull PreparedStatement stmt, @Nonnull CaseDbTransaction caseDbTransaction) {
|
private void insertOrUpdateFile(DrawableFile f, @Nonnull DrawableTransaction tr, @Nonnull CaseDbTransaction caseDbTransaction, boolean addGroups) {
|
||||||
|
|
||||||
|
PreparedStatement stmt;
|
||||||
|
|
||||||
if (tr.isClosed()) {
|
if (tr.isClosed()) {
|
||||||
throw new IllegalArgumentException("can't update database with closed transaction");
|
throw new IllegalArgumentException("can't update database with closed transaction");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// assume that we are doing an update if we are adding groups - i.e. not pre-populating
|
||||||
|
if (addGroups) {
|
||||||
|
stmt = updateFileStmt;
|
||||||
|
} else {
|
||||||
|
stmt = insertFileStmt;
|
||||||
|
}
|
||||||
|
|
||||||
// get data from caches. Default to true and force the DB lookup if we don't have caches
|
// get data from caches. Default to true and force the DB lookup if we don't have caches
|
||||||
boolean hasExif = true;
|
boolean hasExif = true;
|
||||||
boolean hasHashSet = true;
|
boolean hasHashSet = true;
|
||||||
@ -984,6 +1008,13 @@ public final class DrawableDB {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if we are going to just add basic data, then mark flags that we do not have metadata to prevent lookups
|
||||||
|
if (addGroups == false) {
|
||||||
|
hasExif = false;
|
||||||
|
hasHashSet = false;
|
||||||
|
hasTag = false;
|
||||||
|
}
|
||||||
|
|
||||||
dbWriteLock();
|
dbWriteLock();
|
||||||
try {
|
try {
|
||||||
// "INSERT OR IGNORE/ INTO drawable_files (obj_id, data_source_obj_id, path, name, created_time, modified_time, make, model, analyzed)"
|
// "INSERT OR IGNORE/ INTO drawable_files (obj_id, data_source_obj_id, path, name, created_time, modified_time, make, model, analyzed)"
|
||||||
@ -1006,6 +1037,9 @@ public final class DrawableDB {
|
|||||||
// Update the list of file IDs in memory
|
// Update the list of file IDs in memory
|
||||||
addImageFileToList(f.getId());
|
addImageFileToList(f.getId());
|
||||||
|
|
||||||
|
// update the groups if we are not doing pre-populating
|
||||||
|
if (addGroups) {
|
||||||
|
|
||||||
// Update the hash set tables
|
// Update the hash set tables
|
||||||
if (hasHashSet) {
|
if (hasHashSet) {
|
||||||
try {
|
try {
|
||||||
@ -1045,7 +1079,7 @@ public final class DrawableDB {
|
|||||||
}
|
}
|
||||||
Collection<? extends Comparable<?>> vals = attr.getValue(f);
|
Collection<? extends Comparable<?>> vals = attr.getValue(f);
|
||||||
for (Comparable<?> val : vals) {
|
for (Comparable<?> val : vals) {
|
||||||
if (null != val) {
|
if ((null != val) && (val.toString().isEmpty() == false)) {
|
||||||
if (attr == DrawableAttribute.PATH) {
|
if (attr == DrawableAttribute.PATH) {
|
||||||
insertGroup(f.getAbstractFile().getDataSource().getId(), val.toString(), attr, caseDbTransaction);
|
insertGroup(f.getAbstractFile().getDataSource().getId(), val.toString(), attr, caseDbTransaction);
|
||||||
}
|
}
|
||||||
@ -1055,6 +1089,7 @@ public final class DrawableDB {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// @@@ Consider storing more than ID so that we do not need to requery each file during commit
|
// @@@ Consider storing more than ID so that we do not need to requery each file during commit
|
||||||
tr.addUpdatedFile(f.getId());
|
tr.addUpdatedFile(f.getId());
|
||||||
@ -1408,7 +1443,7 @@ public final class DrawableDB {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
String insertSQL = String.format(" (data_source_obj_id, value, attribute) VALUES (%d, \'%s\', \'%s\')",
|
String insertSQL = String.format(" (data_source_obj_id, value, attribute) VALUES (%d, \'%s\', \'%s\')",
|
||||||
ds_obj_id, value, groupBy.attrName.toString());
|
ds_obj_id, SleuthkitCase.escapeSingleQuotes(value), SleuthkitCase.escapeSingleQuotes(groupBy.attrName.toString()));
|
||||||
|
|
||||||
if (DbType.POSTGRESQL == tskCase.getDatabaseType()) {
|
if (DbType.POSTGRESQL == tskCase.getDatabaseType()) {
|
||||||
insertSQL += " ON CONFLICT DO NOTHING";
|
insertSQL += " ON CONFLICT DO NOTHING";
|
||||||
|
@ -68,13 +68,6 @@ public class DrawableGroup implements Comparable<DrawableGroup> {
|
|||||||
DrawableGroup(GroupKey<?> groupKey, Set<Long> filesInGroup, boolean seen) {
|
DrawableGroup(GroupKey<?> groupKey, Set<Long> filesInGroup, boolean seen) {
|
||||||
this.groupKey = groupKey;
|
this.groupKey = groupKey;
|
||||||
this.fileIDs.setAll(filesInGroup);
|
this.fileIDs.setAll(filesInGroup);
|
||||||
fileIDs.addListener((ListChangeListener.Change<? extends Long> listchange) -> {
|
|
||||||
boolean seenChanged = false;
|
|
||||||
while (false == seenChanged && listchange.next()) {
|
|
||||||
seenChanged |= listchange.wasAdded();
|
|
||||||
}
|
|
||||||
invalidateProperties(seenChanged);
|
|
||||||
});
|
|
||||||
this.seen.set(seen);
|
this.seen.set(seen);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,15 +176,21 @@ public class DrawableGroup implements Comparable<DrawableGroup> {
|
|||||||
if (fileIDs.contains(f) == false) {
|
if (fileIDs.contains(f) == false) {
|
||||||
fileIDs.add(f);
|
fileIDs.add(f);
|
||||||
}
|
}
|
||||||
|
// invalidate no matter what because the file could have new hash hits, etc.
|
||||||
|
invalidateProperties(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized void setFiles(Set<? extends Long> newFileIds) {
|
synchronized void setFiles(Set<? extends Long> newFileIds) {
|
||||||
fileIDs.removeIf(fileID -> newFileIds.contains(fileID) == false);
|
fileIDs.removeIf(fileID -> newFileIds.contains(fileID) == false);
|
||||||
|
invalidateProperties(false);
|
||||||
newFileIds.stream().forEach(this::addFile);
|
newFileIds.stream().forEach(this::addFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized void removeFile(Long f) {
|
synchronized void removeFile(Long f) {
|
||||||
|
if (fileIDs.contains(f)) {
|
||||||
fileIDs.removeAll(f);
|
fileIDs.removeAll(f);
|
||||||
|
invalidateProperties(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void invalidateProperties(boolean seenChanged) {
|
private void invalidateProperties(boolean seenChanged) {
|
||||||
|
@ -50,6 +50,7 @@ import javafx.beans.property.ReadOnlyBooleanWrapper;
|
|||||||
import javafx.beans.property.ReadOnlyDoubleProperty;
|
import javafx.beans.property.ReadOnlyDoubleProperty;
|
||||||
import javafx.beans.property.ReadOnlyObjectProperty;
|
import javafx.beans.property.ReadOnlyObjectProperty;
|
||||||
import javafx.beans.property.ReadOnlyObjectWrapper;
|
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||||
|
import javafx.beans.property.ReadOnlyStringProperty;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import javafx.concurrent.Service;
|
import javafx.concurrent.Service;
|
||||||
@ -266,14 +267,23 @@ public class GroupManager {
|
|||||||
try {
|
try {
|
||||||
Examiner examiner = controller.getSleuthKitCase().getCurrentExaminer();
|
Examiner examiner = controller.getSleuthKitCase().getCurrentExaminer();
|
||||||
getDrawableDB().markGroupSeen(group.getGroupKey(), seen, examiner.getId());
|
getDrawableDB().markGroupSeen(group.getGroupKey(), seen, examiner.getId());
|
||||||
|
// only update and reshuffle if its new results
|
||||||
|
if (group.isSeen() != seen) {
|
||||||
group.setSeen(seen);
|
group.setSeen(seen);
|
||||||
updateUnSeenGroups(group);
|
updateUnSeenGroups(group);
|
||||||
|
}
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
logger.log(Level.SEVERE, "Error marking group as seen", ex); //NON-NLS
|
logger.log(Level.SEVERE, "Error marking group as seen", ex); //NON-NLS
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update unseenGroups list accordingly based on the current status of
|
||||||
|
* 'group'. Removes it if it is seen or adds it if it is unseen.
|
||||||
|
*
|
||||||
|
* @param group
|
||||||
|
*/
|
||||||
synchronized private void updateUnSeenGroups(DrawableGroup group) {
|
synchronized private void updateUnSeenGroups(DrawableGroup group) {
|
||||||
if (group.isSeen()) {
|
if (group.isSeen()) {
|
||||||
unSeenGroups.removeAll(group);
|
unSeenGroups.removeAll(group);
|
||||||
@ -496,6 +506,10 @@ public class GroupManager {
|
|||||||
return regrouper.progressProperty();
|
return regrouper.progressProperty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ReadOnlyStringProperty regroupMessage() {
|
||||||
|
return regrouper.messageProperty();
|
||||||
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
synchronized public void handleTagAdded(ContentTagAddedEvent evt) {
|
synchronized public void handleTagAdded(ContentTagAddedEvent evt) {
|
||||||
GroupKey<?> newGroupKey = null;
|
GroupKey<?> newGroupKey = null;
|
||||||
@ -530,16 +544,19 @@ public class GroupManager {
|
|||||||
|
|
||||||
// NOTE: We assume that it has already been determined that GroupKey can be displayed based on Data Source filters
|
// NOTE: We assume that it has already been determined that GroupKey can be displayed based on Data Source filters
|
||||||
if (group == null) {
|
if (group == null) {
|
||||||
//if there wasn't already a group check if there should be one now
|
//if there wasn't already a DrawableGroup, then check if this group is now
|
||||||
// path group, for example, only gets created when all files are analyzed
|
// in an appropriate state to get one made.
|
||||||
|
// Path group, for example, only gets a DrawableGroup created when all files are analyzed
|
||||||
group = popuplateIfAnalyzed(groupKey, null);
|
group = popuplateIfAnalyzed(groupKey, null);
|
||||||
} else {
|
} else {
|
||||||
//if there is aleady a group that was previously deemed fully analyzed, then add this newly analyzed file to it.
|
//if there is aleady a group that was previously deemed fully analyzed, then add this newly analyzed file to it.
|
||||||
group.addFile(fileID);
|
group.addFile(fileID);
|
||||||
}
|
}
|
||||||
// reset the seen status for the group
|
// reset the seen status for the group
|
||||||
|
if (group != null) {
|
||||||
markGroupSeen(group, false);
|
markGroupSeen(group, false);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
synchronized public void handleTagDeleted(ContentTagDeletedEvent evt) {
|
synchronized public void handleTagDeleted(ContentTagDeletedEvent evt) {
|
||||||
@ -607,6 +624,8 @@ public class GroupManager {
|
|||||||
* If the group is analyzed (or other criteria based on grouping) and should
|
* If the group is analyzed (or other criteria based on grouping) and should
|
||||||
* be shown to the user, then add it to the appropriate data structures so
|
* be shown to the user, then add it to the appropriate data structures so
|
||||||
* that it can be viewed.
|
* that it can be viewed.
|
||||||
|
*
|
||||||
|
* @returns null if Group is not ready to be viewed
|
||||||
*/
|
*/
|
||||||
synchronized private DrawableGroup popuplateIfAnalyzed(GroupKey<?> groupKey, ReGroupTask<?> task) {
|
synchronized private DrawableGroup popuplateIfAnalyzed(GroupKey<?> groupKey, ReGroupTask<?> task) {
|
||||||
/*
|
/*
|
||||||
@ -716,12 +735,7 @@ public class GroupManager {
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||||
@NbBundle.Messages({"# {0} - groupBy attribute Name",
|
@NbBundle.Messages({"# {0} - groupBy attribute Name",
|
||||||
"# {1} - sortBy name",
|
"ReGroupTask.displayTitle=regrouping by {0}: " })
|
||||||
"# {2} - sort Order",
|
|
||||||
"ReGroupTask.displayTitle=regrouping files by {0} sorted by {1} in {2} order",
|
|
||||||
"# {0} - groupBy attribute Name",
|
|
||||||
"# {1} - atribute value",
|
|
||||||
"ReGroupTask.progressUpdate=regrouping files by {0} : {1}"})
|
|
||||||
class ReGroupTask<AttrValType extends Comparable<AttrValType>> extends LoggedTask<Void> {
|
class ReGroupTask<AttrValType extends Comparable<AttrValType>> extends LoggedTask<Void> {
|
||||||
|
|
||||||
private final DataSource dataSource;
|
private final DataSource dataSource;
|
||||||
@ -729,16 +743,14 @@ public class GroupManager {
|
|||||||
private final GroupSortBy sortBy;
|
private final GroupSortBy sortBy;
|
||||||
private final SortOrder sortOrder;
|
private final SortOrder sortOrder;
|
||||||
|
|
||||||
private final ProgressHandle groupProgress;
|
|
||||||
|
|
||||||
ReGroupTask(DataSource dataSource, DrawableAttribute<AttrValType> groupBy, GroupSortBy sortBy, SortOrder sortOrder) {
|
ReGroupTask(DataSource dataSource, DrawableAttribute<AttrValType> groupBy, GroupSortBy sortBy, SortOrder sortOrder) {
|
||||||
super(Bundle.ReGroupTask_displayTitle(groupBy.attrName.toString(), sortBy.getDisplayName(), sortOrder.toString()), true);
|
super(Bundle.ReGroupTask_displayTitle(groupBy.attrName.toString() ), true);
|
||||||
this.dataSource = dataSource;
|
this.dataSource = dataSource;
|
||||||
this.groupBy = groupBy;
|
this.groupBy = groupBy;
|
||||||
this.sortBy = sortBy;
|
this.sortBy = sortBy;
|
||||||
this.sortOrder = sortOrder;
|
this.sortOrder = sortOrder;
|
||||||
|
|
||||||
groupProgress = ProgressHandle.createHandle(Bundle.ReGroupTask_displayTitle(groupBy.attrName.toString(), sortBy.getDisplayName(), sortOrder.toString()), this);
|
updateTitle(Bundle.ReGroupTask_displayTitle(groupBy.attrName.toString() ));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -747,7 +759,8 @@ public class GroupManager {
|
|||||||
if (isCancelled()) {
|
if (isCancelled()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
groupProgress.start();
|
|
||||||
|
updateProgress(-1, 1);
|
||||||
|
|
||||||
analyzedGroups.clear();
|
analyzedGroups.clear();
|
||||||
unSeenGroups.clear();
|
unSeenGroups.clear();
|
||||||
@ -755,7 +768,7 @@ public class GroupManager {
|
|||||||
// Get the list of group keys
|
// Get the list of group keys
|
||||||
Multimap<DataSource, AttrValType> valsByDataSource = findValuesForAttribute();
|
Multimap<DataSource, AttrValType> valsByDataSource = findValuesForAttribute();
|
||||||
|
|
||||||
groupProgress.switchToDeterminate(valsByDataSource.entries().size());
|
updateProgress(0, valsByDataSource.entries().size());
|
||||||
int p = 0;
|
int p = 0;
|
||||||
// For each key value, partially create the group and add it to the list.
|
// For each key value, partially create the group and add it to the list.
|
||||||
for (final Map.Entry<DataSource, AttrValType> valForDataSource : valsByDataSource.entries()) {
|
for (final Map.Entry<DataSource, AttrValType> valForDataSource : valsByDataSource.entries()) {
|
||||||
@ -763,9 +776,8 @@ public class GroupManager {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
p++;
|
p++;
|
||||||
updateMessage(Bundle.ReGroupTask_progressUpdate(groupBy.attrName.toString(), valForDataSource.getValue()));
|
updateMessage(Bundle.ReGroupTask_displayTitle(groupBy.attrName.toString()) + valForDataSource.getValue());
|
||||||
updateProgress(p, valsByDataSource.size());
|
updateProgress(p, valsByDataSource.size());
|
||||||
groupProgress.progress(Bundle.ReGroupTask_progressUpdate(groupBy.attrName.toString(), valForDataSource), p);
|
|
||||||
popuplateIfAnalyzed(new GroupKey<>(groupBy, valForDataSource.getValue(), valForDataSource.getKey()), this);
|
popuplateIfAnalyzed(new GroupKey<>(groupBy, valForDataSource.getValue(), valForDataSource.getKey()), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -794,8 +806,8 @@ public class GroupManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
groupProgress.finish();
|
|
||||||
updateProgress(1, 1);
|
updateProgress(1, 1);
|
||||||
|
updateMessage("");
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -813,12 +825,9 @@ public class GroupManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* find the distinct values for the given column (DrawableAttribute)
|
* Find the distinct values for the given column (DrawableAttribute).
|
||||||
*
|
|
||||||
* These values represent the groups of files.
|
* These values represent the groups of files.
|
||||||
*
|
*
|
||||||
* @param groupBy
|
|
||||||
*
|
|
||||||
* @return map of data source (or null if group by attribute ignores
|
* @return map of data source (or null if group by attribute ignores
|
||||||
* data sources) to list of unique group values
|
* data sources) to list of unique group values
|
||||||
*/
|
*/
|
||||||
|
@ -10,12 +10,21 @@
|
|||||||
<?import javafx.scene.layout.HBox?>
|
<?import javafx.scene.layout.HBox?>
|
||||||
<?import javafx.scene.layout.StackPane?>
|
<?import javafx.scene.layout.StackPane?>
|
||||||
|
|
||||||
<fx:root id="AnchorPane" maxHeight="-Infinity" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefHeight="-1.0" prefWidth="-1.0" type="javafx.scene.layout.AnchorPane" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1">
|
<fx:root id="AnchorPane" maxHeight="-Infinity" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefHeight="-1.0" prefWidth="-1.0" type="javafx.scene.layout.AnchorPane" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1">
|
||||||
<children>
|
<children>
|
||||||
<BorderPane minHeight="-Infinity" minWidth="-Infinity" prefHeight="-1.0" prefWidth="-1.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
<BorderPane minHeight="-Infinity" minWidth="-Infinity" prefHeight="-1.0" prefWidth="-1.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
||||||
<right>
|
<right>
|
||||||
<HBox alignment="CENTER_RIGHT" prefHeight="-1.0" prefWidth="-1.0" spacing="5.0" BorderPane.alignment="CENTER_RIGHT">
|
<HBox alignment="CENTER_RIGHT" prefHeight="-1.0" prefWidth="-1.0" spacing="5.0" BorderPane.alignment="CENTER_RIGHT">
|
||||||
<children>
|
<children>
|
||||||
|
<Label fx:id="staleLabel" text="Some data may be out of date. Enable listening to ingest to update.">
|
||||||
|
<graphic>
|
||||||
|
<ImageView fitHeight="16.0" fitWidth="16.0" pickOnBounds="true" preserveRatio="true">
|
||||||
|
<image>
|
||||||
|
<Image url="@../images/information.png" />
|
||||||
|
</image>
|
||||||
|
</ImageView>
|
||||||
|
</graphic>
|
||||||
|
</Label>
|
||||||
<StackPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="-1.0" prefWidth="-1.0" HBox.hgrow="NEVER">
|
<StackPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="-1.0" prefWidth="-1.0" HBox.hgrow="NEVER">
|
||||||
<children>
|
<children>
|
||||||
<ProgressBar id="progBar" fx:id="fileTaskProgresBar" focusTraversable="false" maxHeight="-1.0" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-1.0" prefHeight="24.0" prefWidth="-1.0" progress="0.0" visible="true" />
|
<ProgressBar id="progBar" fx:id="fileTaskProgresBar" focusTraversable="false" maxHeight="-1.0" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-1.0" prefHeight="24.0" prefWidth="-1.0" progress="0.0" visible="true" />
|
||||||
@ -31,37 +40,27 @@
|
|||||||
<Insets />
|
<Insets />
|
||||||
</HBox.margin>
|
</HBox.margin>
|
||||||
</StackPane>
|
</StackPane>
|
||||||
<StackPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="-1.0" prefWidth="-1.0" HBox.hgrow="NEVER">
|
|
||||||
<children>
|
|
||||||
<ProgressBar fx:id="bgTaskProgressBar" maxHeight="-1.0" maxWidth="-1.0" minHeight="-Infinity" minWidth="-1.0" prefHeight="24.0" prefWidth="-1.0" progress="0.0" StackPane.alignment="CENTER" />
|
|
||||||
<Label fx:id="bgTaskLabel" alignment="CENTER" cache="false" contentDisplay="CENTER" disable="false" focusTraversable="false" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" text="" StackPane.alignment="CENTER">
|
|
||||||
<StackPane.margin>
|
|
||||||
<Insets left="3.0" right="3.0" />
|
|
||||||
</StackPane.margin>
|
|
||||||
<padding>
|
|
||||||
<Insets bottom="3.0" left="3.0" right="3.0" top="3.0" />
|
|
||||||
</padding></Label>
|
|
||||||
</children>
|
|
||||||
<HBox.margin>
|
|
||||||
<Insets right="5.0" />
|
|
||||||
</HBox.margin>
|
|
||||||
</StackPane>
|
|
||||||
</children>
|
</children>
|
||||||
<BorderPane.margin>
|
<BorderPane.margin>
|
||||||
<Insets left="10.0" />
|
<Insets left="10.0" />
|
||||||
</BorderPane.margin>
|
</BorderPane.margin>
|
||||||
</HBox>
|
</HBox>
|
||||||
</right>
|
</right>
|
||||||
<left><Label fx:id="staleLabel" text="Some data may be out of date. Enable listening to ingest to update." BorderPane.alignment="CENTER">
|
<left>
|
||||||
<graphic><ImageView fitHeight="16.0" fitWidth="16.0" pickOnBounds="true" preserveRatio="true">
|
<StackPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="-1.0" prefWidth="-1.0" BorderPane.alignment="CENTER">
|
||||||
<image>
|
<children>
|
||||||
<Image url="@../images/information.png" />
|
<ProgressBar fx:id="regroupProgressBar" maxHeight="-1.0" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-1.0" prefHeight="24.0" prefWidth="500.0" progress="0.0" StackPane.alignment="CENTER_LEFT" />
|
||||||
</image></ImageView>
|
<Label fx:id="regroupLabel" cache="false" contentDisplay="CENTER" disable="false" focusTraversable="false" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefWidth="500.0" text="" textOverrun="CENTER_ELLIPSIS" StackPane.alignment="CENTER_LEFT">
|
||||||
</graphic>
|
<StackPane.margin>
|
||||||
<BorderPane.margin>
|
<Insets left="3.0" right="3.0" />
|
||||||
<Insets bottom="5.0" left="5.0" right="10.0" top="5.0" />
|
</StackPane.margin>
|
||||||
</BorderPane.margin></Label>
|
<padding>
|
||||||
</left>
|
<Insets bottom="3.0" left="3.0" right="3.0" top="3.0" />
|
||||||
|
</padding>
|
||||||
|
</Label>
|
||||||
|
</children>
|
||||||
|
</StackPane>
|
||||||
|
</left>
|
||||||
</BorderPane>
|
</BorderPane>
|
||||||
</children>
|
</children>
|
||||||
</fx:root>
|
</fx:root>
|
||||||
|
@ -28,28 +28,26 @@ import javafx.scene.control.Tooltip;
|
|||||||
import javafx.scene.layout.AnchorPane;
|
import javafx.scene.layout.AnchorPane;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
|
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
|
||||||
|
import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class StatusBar extends AnchorPane {
|
public class StatusBar extends AnchorPane {
|
||||||
|
|
||||||
private final ImageGalleryController controller;
|
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private ProgressBar fileTaskProgresBar;
|
private ProgressBar fileTaskProgresBar;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private Label fileUpdateTaskLabel;
|
private Label fileUpdateTaskLabel;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private Label bgTaskLabel;
|
private Label regroupLabel;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private Label staleLabel;
|
private Label staleLabel;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private ProgressBar bgTaskProgressBar;
|
private ProgressBar regroupProgressBar;
|
||||||
|
|
||||||
|
private final ImageGalleryController controller;
|
||||||
|
private final GroupManager groupManager;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
@NbBundle.Messages({"StatusBar.fileUpdateTaskLabel.text= File Update Tasks",
|
@NbBundle.Messages({"StatusBar.fileUpdateTaskLabel.text= File Update Tasks",
|
||||||
@ -58,23 +56,25 @@ public class StatusBar extends AnchorPane {
|
|||||||
void initialize() {
|
void initialize() {
|
||||||
assert fileTaskProgresBar != null : "fx:id=\"fileTaskProgresBar\" was not injected: check your FXML file 'StatusBar.fxml'.";
|
assert fileTaskProgresBar != null : "fx:id=\"fileTaskProgresBar\" was not injected: check your FXML file 'StatusBar.fxml'.";
|
||||||
assert fileUpdateTaskLabel != null : "fx:id=\"fileUpdateTaskLabel\" was not injected: check your FXML file 'StatusBar.fxml'.";
|
assert fileUpdateTaskLabel != null : "fx:id=\"fileUpdateTaskLabel\" was not injected: check your FXML file 'StatusBar.fxml'.";
|
||||||
assert bgTaskLabel != null : "fx:id=\"bgTaskLabel\" was not injected: check your FXML file 'StatusBar.fxml'.";
|
assert regroupLabel != null : "fx:id=\"regroupLabel\" was not injected: check your FXML file 'StatusBar.fxml'.";
|
||||||
assert bgTaskProgressBar != null : "fx:id=\"bgTaskProgressBar\" was not injected: check your FXML file 'StatusBar.fxml'.";
|
assert regroupProgressBar != null : "fx:id=\"regroupProgressBar\" was not injected: check your FXML file 'StatusBar.fxml'.";
|
||||||
|
|
||||||
fileUpdateTaskLabel.textProperty().bind(controller.getDBTasksQueueSizeProperty().asString().concat(Bundle.StatusBar_fileUpdateTaskLabel_text()));
|
fileUpdateTaskLabel.textProperty().bind(controller.getDBTasksQueueSizeProperty().asString().concat(Bundle.StatusBar_fileUpdateTaskLabel_text()));
|
||||||
fileTaskProgresBar.progressProperty().bind(controller.getDBTasksQueueSizeProperty().negate());
|
fileTaskProgresBar.progressProperty().bind(controller.getDBTasksQueueSizeProperty().negate());
|
||||||
|
|
||||||
controller.regroupProgress().addListener((ov, oldSize, newSize) -> {
|
groupManager.regroupProgress().addListener((ov, oldSize, newSize) -> {
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
if (controller.regroupProgress().lessThan(1.0).get()) {
|
if (groupManager.regroupProgress().lessThan(1.0).get()) {
|
||||||
// Regrouping in progress
|
// Regrouping in progress
|
||||||
bgTaskProgressBar.progressProperty().setValue(-1.0);
|
regroupProgressBar.progressProperty().setValue(groupManager.regroupProgress().doubleValue());
|
||||||
bgTaskLabel.setText(Bundle.StatusBar_bgTaskLabel_text());
|
regroupLabel.setText(groupManager.regroupMessage().get());
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Clear the progress bar
|
// Clear the progress bar
|
||||||
bgTaskProgressBar.progressProperty().setValue(0.0);
|
regroupProgressBar.progressProperty().setValue(0.0);
|
||||||
bgTaskLabel.setText("");
|
regroupLabel.setText("");
|
||||||
}
|
}
|
||||||
|
regroupLabel.setTooltip(new Tooltip(regroupLabel.getText()));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -84,6 +84,7 @@ public class StatusBar extends AnchorPane {
|
|||||||
|
|
||||||
public StatusBar(ImageGalleryController controller) {
|
public StatusBar(ImageGalleryController controller) {
|
||||||
this.controller = controller;
|
this.controller = controller;
|
||||||
|
this.groupManager = controller.getGroupManager();
|
||||||
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("StatusBar.fxml")); //NON-NLS
|
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("StatusBar.fxml")); //NON-NLS
|
||||||
fxmlLoader.setRoot(this);
|
fxmlLoader.setRoot(this);
|
||||||
fxmlLoader.setController(this);
|
fxmlLoader.setController(this);
|
||||||
@ -93,6 +94,5 @@ public class StatusBar extends AnchorPane {
|
|||||||
} catch (IOException exception) {
|
} catch (IOException exception) {
|
||||||
throw new RuntimeException(exception);
|
throw new RuntimeException(exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
6
NEWS.txt
6
NEWS.txt
@ -1,3 +1,9 @@
|
|||||||
|
---------------- VERSION 4.9.1 --------------
|
||||||
|
Bug Fixes:
|
||||||
|
- Fixed possible ingest deadlock from Image Gallery database inserts.
|
||||||
|
- Image Gallery does not need lock on Case DB during pre-population, which makes UI more responsive.
|
||||||
|
- Other misc Image Gallery fixes.
|
||||||
|
|
||||||
---------------- VERSION 4.9.0 --------------
|
---------------- VERSION 4.9.0 --------------
|
||||||
|
|
||||||
New Features:
|
New Features:
|
||||||
|
@ -73,9 +73,7 @@
|
|||||||
</run-dependency>
|
</run-dependency>
|
||||||
</dependency>
|
</dependency>
|
||||||
</module-dependencies>
|
</module-dependencies>
|
||||||
<public-packages>
|
<public-packages/>
|
||||||
<package>org.sleuthkit.autopsy.recentactivity</package>
|
|
||||||
</public-packages>
|
|
||||||
<class-path-extension>
|
<class-path-extension>
|
||||||
<runtime-relative-path>ext/gson-2.1.jar</runtime-relative-path>
|
<runtime-relative-path>ext/gson-2.1.jar</runtime-relative-path>
|
||||||
<binary-origin>release/modules/ext/gson-2.1.jar</binary-origin>
|
<binary-origin>release/modules/ext/gson-2.1.jar</binary-origin>
|
||||||
|
@ -37,6 +37,7 @@ import java.util.*;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.NetworkUtils;
|
||||||
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestJobContext;
|
import org.sleuthkit.autopsy.ingest.IngestJobContext;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
@ -309,7 +310,7 @@ final class Chrome extends Extract {
|
|||||||
} else {
|
} else {
|
||||||
date = Long.valueOf(0);
|
date = Long.valueOf(0);
|
||||||
}
|
}
|
||||||
String domain = Util.extractDomain(url);
|
String domain = NetworkUtils.extractDomain(url);
|
||||||
try {
|
try {
|
||||||
Collection<BlackboardAttribute> bbattributes = Arrays.asList(
|
Collection<BlackboardAttribute> bbattributes = Arrays.asList(
|
||||||
new BlackboardAttribute(
|
new BlackboardAttribute(
|
||||||
@ -520,6 +521,7 @@ final class Chrome extends Extract {
|
|||||||
try {
|
try {
|
||||||
BlackboardArtifact bbart = downloadFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD);
|
BlackboardArtifact bbart = downloadFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD);
|
||||||
bbart.addAttributes(bbattributes);
|
bbart.addAttributes(bbattributes);
|
||||||
|
|
||||||
bbartifacts.add(bbart);
|
bbartifacts.add(bbart);
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
logger.log(Level.SEVERE, "Error while trying to insert Chrome download artifact.", ex); //NON-NLS
|
logger.log(Level.SEVERE, "Error while trying to insert Chrome download artifact.", ex); //NON-NLS
|
||||||
@ -589,6 +591,7 @@ final class Chrome extends Extract {
|
|||||||
List<HashMap<String, Object>> tempList = this.dbConnect(temps, LOGIN_QUERY);
|
List<HashMap<String, Object>> tempList = this.dbConnect(temps, LOGIN_QUERY);
|
||||||
logger.log(Level.INFO, "{0}- Now getting login information from {1} with {2}artifacts identified.", new Object[]{getModuleName(), temps, tempList.size()}); //NON-NLS
|
logger.log(Level.INFO, "{0}- Now getting login information from {1} with {2}artifacts identified.", new Object[]{getModuleName(), temps, tempList.size()}); //NON-NLS
|
||||||
for (HashMap<String, Object> result : tempList) {
|
for (HashMap<String, Object> result : tempList) {
|
||||||
|
|
||||||
Collection<BlackboardAttribute> bbattributes = Arrays.asList(
|
Collection<BlackboardAttribute> bbattributes = Arrays.asList(
|
||||||
new BlackboardAttribute(
|
new BlackboardAttribute(
|
||||||
TSK_URL, PARENT_MODULE_NAME,
|
TSK_URL, PARENT_MODULE_NAME,
|
||||||
@ -618,6 +621,7 @@ final class Chrome extends Extract {
|
|||||||
try {
|
try {
|
||||||
BlackboardArtifact bbart = signonFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY);
|
BlackboardArtifact bbart = signonFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY);
|
||||||
bbart.addAttributes(bbattributes);
|
bbart.addAttributes(bbattributes);
|
||||||
|
|
||||||
bbartifacts.add(bbart);
|
bbartifacts.add(bbart);
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
logger.log(Level.SEVERE, "Error while trying to insert Chrome login artifact.", ex); //NON-NLS
|
logger.log(Level.SEVERE, "Error while trying to insert Chrome login artifact.", ex); //NON-NLS
|
||||||
|
@ -159,6 +159,7 @@ class ExtractIE extends Extract {
|
|||||||
try {
|
try {
|
||||||
BlackboardArtifact bbart = fav.newArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK);
|
BlackboardArtifact bbart = fav.newArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK);
|
||||||
bbart.addAttributes(bbattributes);
|
bbart.addAttributes(bbattributes);
|
||||||
|
|
||||||
bbartifacts.add(bbart);
|
bbartifacts.add(bbart);
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
logger.log(Level.SEVERE, "Error while trying to create Internet Explorer bookmark artifact.", ex); //NON-NLS
|
logger.log(Level.SEVERE, "Error while trying to create Internet Explorer bookmark artifact.", ex); //NON-NLS
|
||||||
@ -596,6 +597,7 @@ class ExtractIE extends Extract {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
* Determine if the URL should be ignored.
|
* Determine if the URL should be ignored.
|
||||||
*
|
*
|
||||||
* @param url The URL to test.
|
* @param url The URL to test.
|
||||||
|
@ -22,14 +22,12 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.recentactivity;
|
package org.sleuthkit.autopsy.recentactivity;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import static com.google.common.collect.Lists.newArrayList;
|
import static com.google.common.collect.Lists.newArrayList;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URLDecoder;
|
import java.net.URLDecoder;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -492,7 +490,6 @@ final class FirefoxExtractor extends Extract {
|
|||||||
errors++;
|
errors++;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|
||||||
BlackboardArtifact bbart = downloadsFile.newArtifact(TSK_WEB_DOWNLOAD);
|
BlackboardArtifact bbart = downloadsFile.newArtifact(TSK_WEB_DOWNLOAD);
|
||||||
bbart.addAttributes(bbattributes);
|
bbart.addAttributes(bbattributes);
|
||||||
bbartifacts.add(bbart);
|
bbartifacts.add(bbart);
|
||||||
@ -642,10 +639,11 @@ final class FirefoxExtractor extends Extract {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
||||||
* Determine if the URL should be ignored.
|
* Determine if the URL should be ignored.
|
||||||
*
|
*
|
||||||
* @param url The URL to test.
|
* @param url The URL to test.
|
||||||
*
|
*s
|
||||||
* @return True if the URL should be ignored; otherwise false.
|
* @return True if the URL should be ignored; otherwise false.
|
||||||
*/
|
*/
|
||||||
private boolean isIgnoredUrl(String url) {
|
private boolean isIgnoredUrl(String url) {
|
||||||
|
@ -50,11 +50,11 @@ import org.sleuthkit.datamodel.TskCoreException;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Alex
|
*
|
||||||
*/
|
*/
|
||||||
class Util {
|
class Util {
|
||||||
|
|
||||||
private static Logger logger = Logger.getLogger(Util.class.getName());
|
private static final Logger logger = Logger.getLogger(Util.class.getName());
|
||||||
|
|
||||||
private Util() {
|
private Util() {
|
||||||
}
|
}
|
||||||
@ -83,8 +83,10 @@ class Util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
//JIRA-2384: There is no utility in apache or guave to do this for us?
|
* //JIRA-2384: There is no utility in apache or guave to do this for us?
|
||||||
|
*
|
||||||
* @param url
|
* @param url
|
||||||
|
*
|
||||||
* @return empty string if no domain could be found
|
* @return empty string if no domain could be found
|
||||||
*/
|
*/
|
||||||
private static String getBaseDomain(String url) {
|
private static String getBaseDomain(String url) {
|
||||||
@ -111,7 +113,6 @@ class Util {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
String base = hostB.toString();
|
String base = hostB.toString();
|
||||||
// verify there are no special characters in there
|
// verify there are no special characters in there
|
||||||
if (base.matches(".*[~`!@#$%^&\\*\\(\\)\\+={}\\[\\];:\\?<>,/ ].*")) {
|
if (base.matches(".*[~`!@#$%^&\\*\\(\\)\\+={}\\[\\];:\\?<>,/ ].*")) {
|
||||||
@ -123,6 +124,7 @@ class Util {
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param value
|
* @param value
|
||||||
|
*
|
||||||
* @return empty string if no domain name was found
|
* @return empty string if no domain name was found
|
||||||
*/
|
*/
|
||||||
public static String extractDomain(String value) {
|
public static String extractDomain(String value) {
|
||||||
@ -156,18 +158,8 @@ class Util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String getFileName(String value) {
|
public static String getFileName(String value) {
|
||||||
String filename = "";
|
|
||||||
String filematch = "^([a-zA-Z]\\:)(\\\\[^\\\\/:*?<>\"|]*(?<!\\[ \\]))*(\\.[a-zA-Z]{2,6})$"; //NON-NLS
|
|
||||||
|
|
||||||
Pattern p = Pattern.compile(filematch, Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.COMMENTS);
|
|
||||||
Matcher m = p.matcher(value);
|
|
||||||
if (m.find()) {
|
|
||||||
filename = m.group(1);
|
|
||||||
|
|
||||||
}
|
|
||||||
int lastPos = value.lastIndexOf('\\');
|
int lastPos = value.lastIndexOf('\\');
|
||||||
filename = (lastPos < 0) ? value : value.substring(lastPos + 1);
|
return (lastPos < 0) ? value : value.substring(lastPos + 1);
|
||||||
return filename.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getPath(String txt) {
|
public static String getPath(String txt) {
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
<project name="TSK_VERSION">
|
<project name="TSK_VERSION">
|
||||||
<property name="TSK_VERSION" value="4.6.3"/>
|
<property name="TSK_VERSION" value="4.6.4"/>
|
||||||
</project>
|
</project>
|
||||||
|
@ -38,7 +38,7 @@ PROJECT_NAME = "Autopsy User Documentation"
|
|||||||
# could be handy for archiving the generated documentation or if some version
|
# could be handy for archiving the generated documentation or if some version
|
||||||
# control system is used.
|
# control system is used.
|
||||||
|
|
||||||
PROJECT_NUMBER = 4.9.0
|
PROJECT_NUMBER = 4.9.1
|
||||||
|
|
||||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||||
# for a project that appears at the top of each page and should give viewer a
|
# for a project that appears at the top of each page and should give viewer a
|
||||||
|
@ -38,7 +38,7 @@ PROJECT_NAME = "Autopsy"
|
|||||||
# could be handy for archiving the generated documentation or if some version
|
# could be handy for archiving the generated documentation or if some version
|
||||||
# control system is used.
|
# control system is used.
|
||||||
|
|
||||||
PROJECT_NUMBER = 4.9.0
|
PROJECT_NUMBER = 4.9.1
|
||||||
|
|
||||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||||
# for a project that appears a the top of each page and should give viewer a
|
# for a project that appears a the top of each page and should give viewer a
|
||||||
|
@ -4,10 +4,10 @@ app.title=Autopsy
|
|||||||
### lowercase version of above
|
### lowercase version of above
|
||||||
app.name=${branding.token}
|
app.name=${branding.token}
|
||||||
### if left unset, version will default to today's date
|
### if left unset, version will default to today's date
|
||||||
app.version=4.9.0
|
app.version=4.9.1
|
||||||
### build.type must be one of: DEVELOPMENT, RELEASE
|
### build.type must be one of: DEVELOPMENT, RELEASE
|
||||||
#build.type=RELEASE
|
build.type=RELEASE
|
||||||
build.type=DEVELOPMENT
|
#build.type=DEVELOPMENT
|
||||||
|
|
||||||
project.org.netbeans.progress=org-netbeans-api-progress
|
project.org.netbeans.progress=org-netbeans-api-progress
|
||||||
project.org.sleuthkit.autopsy.experimental=Experimental
|
project.org.sleuthkit.autopsy.experimental=Experimental
|
||||||
|
268
release/update_autopsy_version.pl
Executable file
268
release/update_autopsy_version.pl
Executable file
@ -0,0 +1,268 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
# Updates various Autopsy version numbers
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use File::Copy;
|
||||||
|
|
||||||
|
# global variables
|
||||||
|
my $VER;
|
||||||
|
|
||||||
|
|
||||||
|
my $TESTING = 0;
|
||||||
|
print "TESTING MODE (no commits)\n" if ($TESTING);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
sub main {
|
||||||
|
|
||||||
|
# Get the Autopsy version argument
|
||||||
|
if (scalar (@ARGV) != 1) {
|
||||||
|
print stderr "Missing release version argument (i.e. 4.9.0)\n";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$VER = $ARGV[0];
|
||||||
|
die "Invalid version number: $VER (1.2.3 or 1.2.3b1 expected)" unless ($VER =~ /^\d+\.\d+\.\d+(b\d+)?$/);
|
||||||
|
|
||||||
|
|
||||||
|
my $AUT_RELNAME = "autopsy-${VER}";
|
||||||
|
# Verify the tag doesn't already exist
|
||||||
|
exec_pipe(*OUT, "git tag | grep \"${AUT_RELNAME}\$\"");
|
||||||
|
my $foo = read_pipe_line(*OUT);
|
||||||
|
if ($foo ne "") {
|
||||||
|
print "Tag ${AUT_RELNAME} already exists\n";
|
||||||
|
print "Remove with 'git tag -d ${AUT_RELNAME}'\n";
|
||||||
|
die "stopping";
|
||||||
|
}
|
||||||
|
close(OUT);
|
||||||
|
|
||||||
|
# Assume we running out of 'release' folder
|
||||||
|
chdir ".." or die "Error changing directories to root";
|
||||||
|
|
||||||
|
|
||||||
|
# verify_precheckin();
|
||||||
|
|
||||||
|
|
||||||
|
# Update the version info in that tag
|
||||||
|
update_project_properties();
|
||||||
|
update_doxygen_dev();
|
||||||
|
update_doxygen_user();
|
||||||
|
|
||||||
|
print "Files updated. You need to commit and push them\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
######################################################
|
||||||
|
# Utility functions
|
||||||
|
|
||||||
|
|
||||||
|
# Function to execute a command and send output to pipe
|
||||||
|
# returns handle
|
||||||
|
# exec_pipe(HANDLE, CMD);
|
||||||
|
sub exec_pipe {
|
||||||
|
my $handle = shift(@_);
|
||||||
|
my $cmd = shift(@_);
|
||||||
|
|
||||||
|
die "Can't open pipe for exec_pipe"
|
||||||
|
unless defined(my $pid = open($handle, '-|'));
|
||||||
|
|
||||||
|
if ($pid) {
|
||||||
|
return $handle;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$| = 1;
|
||||||
|
exec("$cmd") or die "Can't exec program: $!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Read a line of text from an open exec_pipe handle
|
||||||
|
sub read_pipe_line {
|
||||||
|
my $handle = shift(@_);
|
||||||
|
my $out;
|
||||||
|
|
||||||
|
for (my $i = 0; $i < 100; $i++) {
|
||||||
|
$out = <$handle>;
|
||||||
|
return $out if (defined $out);
|
||||||
|
}
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Prompt user for argument and return response
|
||||||
|
sub prompt_user {
|
||||||
|
my $q = shift(@_);
|
||||||
|
print "$q: ";
|
||||||
|
$| = 1;
|
||||||
|
$_ = <STDIN>;
|
||||||
|
chomp;
|
||||||
|
return $_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#############################################
|
||||||
|
# File update methods
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Verify that all files in the current source directory
|
||||||
|
# are checked in. dies if any are modified.
|
||||||
|
sub verify_precheckin {
|
||||||
|
|
||||||
|
#system ("git pull");
|
||||||
|
|
||||||
|
print "Verifying everything is checked in\n";
|
||||||
|
exec_pipe(*OUT, "git status -s | grep \"^ M\"");
|
||||||
|
|
||||||
|
my $foo = read_pipe_line(*OUT);
|
||||||
|
if ($foo ne "") {
|
||||||
|
print "Files not checked in\n";
|
||||||
|
while ($foo ne "") {
|
||||||
|
print "$foo";
|
||||||
|
$foo = read_pipe_line(*OUT);
|
||||||
|
}
|
||||||
|
die "stopping" unless ($TESTING);
|
||||||
|
}
|
||||||
|
close(OUT);
|
||||||
|
|
||||||
|
print "Verifying everything is pushed\n";
|
||||||
|
exec_pipe(*OUT, "git status -sb | grep \"^##\" | grep \"ahead \"");
|
||||||
|
my $foo = read_pipe_line(*OUT);
|
||||||
|
if ($foo ne "") {
|
||||||
|
print "$foo";
|
||||||
|
print "Files not pushed to remote\n";
|
||||||
|
die "stopping" unless ($TESTING);
|
||||||
|
}
|
||||||
|
close(OUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# update the version in nbproject/project.properties
|
||||||
|
sub update_project_properties {
|
||||||
|
|
||||||
|
my $orig = "project.properties";
|
||||||
|
my $temp = "${orig}-bak";
|
||||||
|
|
||||||
|
print "Updating the version in ${orig}\n";
|
||||||
|
|
||||||
|
chdir "nbproject" or die "cannot change into nbproject directory";
|
||||||
|
|
||||||
|
|
||||||
|
open (CONF_IN, "<${orig}") or die "Cannot open ${orig}";
|
||||||
|
open (CONF_OUT, ">${temp}") or die "Cannot open ${temp}";
|
||||||
|
|
||||||
|
my $found = 0;
|
||||||
|
while (<CONF_IN>) {
|
||||||
|
if (/^app\.version=/) {
|
||||||
|
print CONF_OUT "app.version=$VER\n";
|
||||||
|
$found++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print CONF_OUT $_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close (CONF_IN);
|
||||||
|
close (CONF_OUT);
|
||||||
|
|
||||||
|
if ($found != 1) {
|
||||||
|
die "$found (instead of 1) occurrences of app.version found in ${orig}";
|
||||||
|
}
|
||||||
|
|
||||||
|
unlink ($orig) or die "Error deleting ${orig}";
|
||||||
|
rename ($temp, $orig) or die "Error renaming tmp $orig file";
|
||||||
|
system("git add ${orig}") unless ($TESTING);
|
||||||
|
chdir ".." or die "Error changing directories back to root";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# update the dev docs
|
||||||
|
sub update_doxygen_dev {
|
||||||
|
|
||||||
|
my $orig = "Doxyfile";
|
||||||
|
my $temp = "${orig}-bak";
|
||||||
|
|
||||||
|
print "Updating the version in ${orig} (Dev)\n";
|
||||||
|
|
||||||
|
chdir "docs/doxygen" or die "cannot change into docs/doxygen directory";
|
||||||
|
|
||||||
|
|
||||||
|
open (CONF_IN, "<${orig}") or die "Cannot open ${orig}";
|
||||||
|
open (CONF_OUT, ">${temp}") or die "Cannot open ${temp}";
|
||||||
|
|
||||||
|
my $found = 0;
|
||||||
|
while (<CONF_IN>) {
|
||||||
|
if (/^PROJECT_NUMBER/) {
|
||||||
|
print CONF_OUT "PROJECT_NUMBER = ${VER}\n";
|
||||||
|
$found++;
|
||||||
|
}
|
||||||
|
elsif (/^HTML_OUTPUT/) {
|
||||||
|
print CONF_OUT "HTML_OUTPUT = api-docs/${VER}/\n";
|
||||||
|
$found++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print CONF_OUT $_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close (CONF_IN);
|
||||||
|
close (CONF_OUT);
|
||||||
|
|
||||||
|
if ($found != 2) {
|
||||||
|
die "$found (instead of 2) occurrences of version found in (DEV) ${orig}";
|
||||||
|
}
|
||||||
|
|
||||||
|
unlink ($orig) or die "Error deleting ${orig}";
|
||||||
|
rename ($temp, $orig) or die "Error renaming tmp $orig file";
|
||||||
|
system("git add ${orig}") unless ($TESTING);
|
||||||
|
chdir "../.." or die "Error changing directories back to root";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# update the user docs
|
||||||
|
sub update_doxygen_user {
|
||||||
|
|
||||||
|
my $orig = "Doxyfile";
|
||||||
|
my $temp = "${orig}-bak";
|
||||||
|
|
||||||
|
print "Updating the version in ${orig} (User)\n";
|
||||||
|
|
||||||
|
chdir "docs/doxygen-user" or die "cannot change into docs/doxygen-user directory";
|
||||||
|
|
||||||
|
|
||||||
|
open (CONF_IN, "<${orig}") or die "Cannot open ${orig}";
|
||||||
|
open (CONF_OUT, ">${temp}") or die "Cannot open ${temp}";
|
||||||
|
|
||||||
|
my $found = 0;
|
||||||
|
while (<CONF_IN>) {
|
||||||
|
if (/^PROJECT_NUMBER/) {
|
||||||
|
print CONF_OUT "PROJECT_NUMBER = ${VER}\n";
|
||||||
|
$found++;
|
||||||
|
}
|
||||||
|
elsif (/^HTML_OUTPUT/) {
|
||||||
|
print CONF_OUT "HTML_OUTPUT = ${VER}\n";
|
||||||
|
$found++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print CONF_OUT $_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close (CONF_IN);
|
||||||
|
close (CONF_OUT);
|
||||||
|
|
||||||
|
if ($found != 2) {
|
||||||
|
die "$found (instead of 2) occurrences of version found in (USER) ${orig}";
|
||||||
|
}
|
||||||
|
|
||||||
|
unlink ($orig) or die "Error deleting ${orig}";
|
||||||
|
rename ($temp, $orig) or die "Error renaming tmp $orig file";
|
||||||
|
system("git add ${orig}") unless ($TESTING);
|
||||||
|
chdir "../.." or die "Error changing directories back to root";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
main();
|
199
release/update_sleuthkit_version.pl
Executable file
199
release/update_sleuthkit_version.pl
Executable file
@ -0,0 +1,199 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
# Updates various TSK version numbers
|
||||||
|
# use this when the version of TSK that Autopsy depends on changes
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use File::Copy;
|
||||||
|
|
||||||
|
# global variables
|
||||||
|
my $VER;
|
||||||
|
|
||||||
|
my $TESTING = 0;
|
||||||
|
print "TESTING MODE (no commits)\n" if ($TESTING);
|
||||||
|
|
||||||
|
|
||||||
|
sub main {
|
||||||
|
|
||||||
|
# Get the TSK version argument
|
||||||
|
if (scalar (@ARGV) != 1) {
|
||||||
|
print stderr "Missing release version argument (i.e. 4.9.0)\n";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$VER = $ARGV[0];
|
||||||
|
die "Invalid version number: $VER (1.2.3 or 1.2.3b1 expected)" unless ($VER =~ /^\d+\.\d+\.\d+(b\d+)?$/);
|
||||||
|
|
||||||
|
# Assume we running out of 'release' folder
|
||||||
|
chdir ".." or die "Error changing directories to root";
|
||||||
|
|
||||||
|
# Update the version info in that tag
|
||||||
|
update_tsk_version();
|
||||||
|
update_core_project_properties();
|
||||||
|
update_core_project_xml();
|
||||||
|
|
||||||
|
print "Files updated. You need to commit and push them\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
######################################################
|
||||||
|
# Utility functions
|
||||||
|
|
||||||
|
|
||||||
|
# Function to execute a command and send output to pipe
|
||||||
|
# returns handle
|
||||||
|
# exec_pipe(HANDLE, CMD);
|
||||||
|
sub exec_pipe {
|
||||||
|
my $handle = shift(@_);
|
||||||
|
my $cmd = shift(@_);
|
||||||
|
|
||||||
|
die "Can't open pipe for exec_pipe"
|
||||||
|
unless defined(my $pid = open($handle, '-|'));
|
||||||
|
|
||||||
|
if ($pid) {
|
||||||
|
return $handle;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$| = 1;
|
||||||
|
exec("$cmd") or die "Can't exec program: $!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Read a line of text from an open exec_pipe handle
|
||||||
|
sub read_pipe_line {
|
||||||
|
my $handle = shift(@_);
|
||||||
|
my $out;
|
||||||
|
|
||||||
|
for (my $i = 0; $i < 100; $i++) {
|
||||||
|
$out = <$handle>;
|
||||||
|
return $out if (defined $out);
|
||||||
|
}
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#############################################
|
||||||
|
# File update methods
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# update the tskversion.xml
|
||||||
|
sub update_tsk_version {
|
||||||
|
|
||||||
|
my $orig = "TSKVersion.xml";
|
||||||
|
my $temp = "${orig}-bak";
|
||||||
|
|
||||||
|
print "Updating the version in ${orig}\n";
|
||||||
|
|
||||||
|
open (CONF_IN, "<${orig}") or die "Cannot open ${orig}";
|
||||||
|
open (CONF_OUT, ">${temp}") or die "Cannot open ${temp}";
|
||||||
|
|
||||||
|
my $found = 0;
|
||||||
|
while (<CONF_IN>) {
|
||||||
|
if (/name="TSK_VERSION" value=/) {
|
||||||
|
print CONF_OUT " <property name=\"TSK_VERSION\" value=\"${VER}\"/>\n";
|
||||||
|
$found++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print CONF_OUT $_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close (CONF_IN);
|
||||||
|
close (CONF_OUT);
|
||||||
|
|
||||||
|
if ($found != 1) {
|
||||||
|
die "$found (instead of 1) occurrences of app.version found in ${orig}";
|
||||||
|
}
|
||||||
|
|
||||||
|
unlink ($orig) or die "Error deleting ${orig}";
|
||||||
|
rename ($temp, $orig) or die "Error renaming tmp $orig file";
|
||||||
|
system("git add ${orig}") unless ($TESTING);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
sub update_core_project_properties {
|
||||||
|
|
||||||
|
my $orig = "project.properties";
|
||||||
|
my $temp = "${orig}-bak";
|
||||||
|
|
||||||
|
print "Updating the version in ${orig}\n";
|
||||||
|
|
||||||
|
chdir "Core/nbproject" or die "cannot change into Core/nbproject directory";
|
||||||
|
|
||||||
|
|
||||||
|
open (CONF_IN, "<${orig}") or die "Cannot open ${orig}";
|
||||||
|
open (CONF_OUT, ">${temp}") or die "Cannot open ${temp}";
|
||||||
|
|
||||||
|
my $found = 0;
|
||||||
|
while (<CONF_IN>) {
|
||||||
|
if (/^file\.reference\.sleuthkit\-postgresql-/) {
|
||||||
|
print CONF_OUT "file.reference.sleuthkit-postgresql-${VER}.jar=release/modules/ext/sleuthkit-postgresql-${VER}.jar\n";
|
||||||
|
$found++;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
print CONF_OUT $_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close (CONF_IN);
|
||||||
|
close (CONF_OUT);
|
||||||
|
|
||||||
|
if ($found != 1) {
|
||||||
|
die "$found (instead of 1) occurrences of version found in ${orig}";
|
||||||
|
}
|
||||||
|
|
||||||
|
unlink ($orig) or die "Error deleting ${orig}";
|
||||||
|
rename ($temp, $orig) or die "Error renaming tmp $orig file";
|
||||||
|
system("git add ${orig}") unless ($TESTING);
|
||||||
|
chdir "../.." or die "Error changing directories back to root";
|
||||||
|
}
|
||||||
|
|
||||||
|
sub update_core_project_xml {
|
||||||
|
|
||||||
|
my $orig = "project.xml";
|
||||||
|
my $temp = "${orig}-bak";
|
||||||
|
|
||||||
|
print "Updating the version in ${orig}\n";
|
||||||
|
|
||||||
|
chdir "Core/nbproject" or die "cannot change into Core/nbproject directory";
|
||||||
|
|
||||||
|
open (CONF_IN, "<${orig}") or die "Cannot open ${orig}";
|
||||||
|
open (CONF_OUT, ">${temp}") or die "Cannot open ${temp}";
|
||||||
|
|
||||||
|
my $found = 0;
|
||||||
|
while (<CONF_IN>) {
|
||||||
|
if (/<runtime-relative-path>ext\/sleuthkit-postgresql/) {
|
||||||
|
print CONF_OUT " <runtime-relative-path>ext/sleuthkit-postgresql-${VER}.jar</runtime-relative-path>\n";
|
||||||
|
$found++;
|
||||||
|
}
|
||||||
|
elsif (/<binary-origin>release\/modules\/ext\/sleuthkit-postgresql/) {
|
||||||
|
print CONF_OUT " <binary-origin>release/modules/ext/sleuthkit-postgresql-${VER}.jar</binary-origin>\n";
|
||||||
|
$found++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print CONF_OUT $_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close (CONF_IN);
|
||||||
|
close (CONF_OUT);
|
||||||
|
|
||||||
|
if ($found != 2) {
|
||||||
|
die "$found (instead of 2) occurrences of version found in ${orig}";
|
||||||
|
}
|
||||||
|
|
||||||
|
unlink ($orig) or die "Error deleting ${orig}";
|
||||||
|
rename ($temp, $orig) or die "Error renaming tmp $orig file";
|
||||||
|
system("git add ${orig}") unless ($TESTING);
|
||||||
|
chdir "../.." or die "Error changing directories back to root";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
main();
|
Loading…
x
Reference in New Issue
Block a user