mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-15 01:07:42 +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="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-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.StixLib.jar=release/modules/ext/StixLib.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-encrypt-2.1.2.jar=release/modules/ext/jackcess-encrypt-2.1.2.jar
|
||||
file.reference.jackcess-2.2.0.jar=release/modules/ext/jackcess-2.2.0.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.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
|
||||
@ -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.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.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-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
|
||||
|
@ -342,8 +342,8 @@
|
||||
<package>org.sleuthkit.datamodel</package>
|
||||
</public-packages>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/jackcess-2.1.8.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/jackcess-2.1.8.jar</binary-origin>
|
||||
<runtime-relative-path>ext/jackcess-2.2.0.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/jackcess-2.2.0.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<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>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/sleuthkit-postgresql-4.6.3.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/sleuthkit-postgresql-4.6.3.jar</binary-origin>
|
||||
<runtime-relative-path>ext/sleuthkit-postgresql-4.6.4.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/sleuthkit-postgresql-4.6.4.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<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>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/jackcess-encrypt-2.1.2.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/jackcess-encrypt-2.1.2.jar</binary-origin>
|
||||
<runtime-relative-path>ext/jackcess-encrypt-2.1.4.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/jackcess-encrypt-2.1.4.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<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.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskUnsupportedSchemaVersionException;
|
||||
import org.sleuthkit.autopsy.coreutils.StopWatch;
|
||||
|
||||
/**
|
||||
* 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."
|
||||
})
|
||||
public static void deleteCase(CaseMetadata metadata) throws CaseActionException {
|
||||
StopWatch stopWatch = new StopWatch();
|
||||
stopWatch.start();
|
||||
synchronized (caseActionSerializationLock) {
|
||||
if (null != currentCase) {
|
||||
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
|
||||
@ -769,10 +774,19 @@ public class Case {
|
||||
* cannot be deleted if another node has it open.
|
||||
*/
|
||||
progressIndicator.progress(Bundle.Case_progressMessage_checkingForOtherUser());
|
||||
stopWatch.reset();
|
||||
stopWatch.start();
|
||||
try (CoordinationService.Lock dirLock = CoordinationService.getInstance().tryGetExclusiveLock(CategoryNode.CASES, metadata.getCaseDirectory())) {
|
||||
assert (null != dirLock);
|
||||
deleteCase(metadata, progressIndicator);
|
||||
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);
|
||||
} else {
|
||||
throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireDirLock());
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
@ -982,11 +996,13 @@ public class Case {
|
||||
"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 {
|
||||
StopWatch stopWatch = new StopWatch();
|
||||
boolean errorsOccurred = false;
|
||||
if (CaseType.MULTI_USER_CASE == metadata.getCaseType()) {
|
||||
/*
|
||||
* Delete the case database from the database server.
|
||||
*/
|
||||
stopWatch.start();
|
||||
try {
|
||||
progressIndicator.progress(Bundle.Case_progressMessage_deletingCaseDatabase());
|
||||
CaseDbConnectionInfo db;
|
||||
@ -996,10 +1012,14 @@ public class Case {
|
||||
Statement statement = connection.createStatement();) {
|
||||
String deleteCommand = "DROP DATABASE \"" + metadata.getCaseDatabaseName() + "\""; //NON-NLS
|
||||
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) {
|
||||
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;
|
||||
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());
|
||||
for (KeywordSearchService searchService : Lookup.getDefault().lookupAll(KeywordSearchService.class)) {
|
||||
try {
|
||||
stopWatch.reset();
|
||||
stopWatch.start();
|
||||
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) {
|
||||
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;
|
||||
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.
|
||||
*/
|
||||
progressIndicator.progress(Bundle.Case_progressMessage_deletingCaseDirectory());
|
||||
stopWatch.reset();
|
||||
stopWatch.start();
|
||||
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()));
|
||||
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)
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
public void notifyCentralRepoCommentChanged(long contentId, String newComment) {
|
||||
@ -1836,7 +1871,7 @@ public class Case {
|
||||
progressIndicator.progress(Bundle.Case_progressMessage_preparingToOpenCaseResources());
|
||||
acquireSharedCaseDirLock(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);
|
||||
} catch (CaseActionException ex) {
|
||||
releaseSharedCaseDirLock(getMetadata().getCaseDirectory());
|
||||
@ -2414,7 +2449,7 @@ public class Case {
|
||||
* @throws CaseActionException with a user-friendly message if the lock
|
||||
* 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 {
|
||||
try {
|
||||
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.util.Calendar;
|
||||
import java.util.List;
|
||||
import java.util.SimpleTimeZone;
|
||||
import java.util.TimeZone;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.JFileChooser;
|
||||
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.ModuleSettings;
|
||||
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
|
||||
@ -72,11 +71,7 @@ public class ImageFilePanel extends JPanel implements DocumentListener {
|
||||
initComponents();
|
||||
|
||||
// Populate the drop down list of time zones
|
||||
for (String id : SimpleTimeZone.getAvailableIDs()) {
|
||||
timeZoneComboBox.addItem(timeZoneToString(TimeZone.getTimeZone(id)));
|
||||
}
|
||||
// set the selected timezone to the current timezone
|
||||
timeZoneComboBox.setSelectedItem(timeZoneToString(Calendar.getInstance().getTimeZone()));
|
||||
createTimeZoneList();
|
||||
|
||||
// Populate the drop down list of sector size options
|
||||
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.
|
||||
*
|
||||
@ -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
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
updateHelper();
|
||||
|
@ -21,8 +21,7 @@ package org.sleuthkit.autopsy.casemodule;
|
||||
import java.io.File;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Calendar;
|
||||
import java.util.SimpleTimeZone;
|
||||
import java.util.TimeZone;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.JFileChooser;
|
||||
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.MessageNotifyUtil;
|
||||
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
||||
import org.sleuthkit.autopsy.coreutils.TimeZoneUtils;
|
||||
import org.sleuthkit.autopsy.imagewriter.ImageWriterSettings;
|
||||
|
||||
/**
|
||||
@ -469,36 +469,13 @@ final class LocalDiskPanel extends JPanel {
|
||||
* to the local machine time zone.
|
||||
*/
|
||||
public void createTimeZoneList() {
|
||||
// load and add all timezone
|
||||
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
|
||||
|
||||
/*
|
||||
* 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);
|
||||
List<String> timeZoneList = TimeZoneUtils.createTimeZoneList();
|
||||
for (String timeZone : timeZoneList) {
|
||||
timeZoneComboBox.addItem(timeZone);
|
||||
}
|
||||
// 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
|
||||
timeZoneComboBox.setSelectedItem(formatted);
|
||||
|
||||
timeZoneComboBox.setSelectedItem(TimeZoneUtils.createTimeZoneString(Calendar.getInstance().getTimeZone()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -369,7 +369,7 @@ public class LocalFilesDSProcessor implements DataSourceProcessor, AutoIngestDat
|
||||
@Override
|
||||
public void process(String deviceId, Path dataSourcePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
|
||||
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 = null;
|
||||
|
||||
/*
|
||||
* Publish content added events for the added files and directories.
|
||||
@ -502,15 +503,14 @@ public class FileManager implements Closeable {
|
||||
|
||||
return dataSource;
|
||||
|
||||
} catch (TskCoreException ex) {
|
||||
} finally {
|
||||
if (null != trans) {
|
||||
try {
|
||||
trans.rollback();
|
||||
} catch (TskCoreException ex2) {
|
||||
LOGGER.log(Level.SEVERE, String.format("Failed to rollback transaction after exception: %s", ex.getMessage()), ex2);
|
||||
} catch (TskCoreException ex) {
|
||||
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"));
|
||||
}
|
||||
|
||||
CorrelationCase eamCase = new CorrelationCase(resultSet.getInt("case_id"), resultSet.getString("case_uid"), resultSet.getString("case_name"));
|
||||
eamCase.setOrg(eamOrg);
|
||||
eamCase.setCreationDate(resultSet.getString("creation_date"));
|
||||
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"));
|
||||
CorrelationCase eamCase = new CorrelationCase(resultSet.getInt("case_id"), resultSet.getString("case_uid"), eamOrg, resultSet.getString("case_name"),
|
||||
resultSet.getString("creation_date"), resultSet.getString("case_number"), resultSet.getString("examiner_name"),
|
||||
resultSet.getString("examiner_email"), resultSet.getString("examiner_phone"), resultSet.getString("notes"));
|
||||
|
||||
|
||||
return eamCase;
|
||||
}
|
||||
@ -3017,7 +3013,6 @@ abstract class AbstractSqlEamDb implements EamDb {
|
||||
if (null == resultSet) {
|
||||
return null;
|
||||
}
|
||||
// @@@ We should have data source ID in the previous query instead of passing -1 into the below constructor
|
||||
return new CorrelationAttributeInstance(
|
||||
aType,
|
||||
resultSet.getString("value"),
|
||||
|
@ -66,7 +66,7 @@ GlobalSettingsPanel.lbCentralRepository.text=A central repository allows you to
|
||||
GlobalSettingsPanel.pnCorrelationProperties.border.title=Correlation Properties
|
||||
GlobalSettingsPanel.organizationPanel.border.title=Organizations
|
||||
GlobalSettingsPanel.casesPanel.border.title=Case Details
|
||||
GlobalSettingsPanel.showCasesButton.text=Show Cases
|
||||
GlobalSettingsPanel.showCasesButton.text=Manage Cases
|
||||
ShowCasesDialog.closeButton.AccessibleContext.accessibleName=Close
|
||||
ShowCasesDialog.closeButton.actionCommand=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.
|
||||
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!
|
||||
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
|
||||
store();
|
||||
ShowCasesDialog showCasesDialog = new ShowCasesDialog();
|
||||
ManageCasesDialog.displayManageCasesDialog();
|
||||
}//GEN-LAST:event_showCasesButtonActionPerformed
|
||||
|
||||
@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,23 +303,25 @@
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" 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">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Component id="endCheckBox" linkSize="1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="12" max="-2" attributes="0"/>
|
||||
<Component id="endDatePicker" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="startCheckBox" linkSize="1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="12" max="-2" attributes="0"/>
|
||||
<Component id="startDatePicker" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="dateRangeLabel" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Component id="endCheckBox" linkSize="1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="12" max="-2" attributes="0"/>
|
||||
<Component id="endDatePicker" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="startCheckBox" linkSize="1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="12" max="-2" attributes="0"/>
|
||||
<Component id="startDatePicker" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
|
@ -124,7 +124,8 @@ final public class FiltersPanel extends JPanel {
|
||||
|
||||
updateFilters(true);
|
||||
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();
|
||||
}
|
||||
});
|
||||
@ -175,7 +176,7 @@ final public class FiltersPanel extends JPanel {
|
||||
}
|
||||
|
||||
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.ZoneOffset;
|
||||
import java.util.TimeZone;
|
||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||
import org.sleuthkit.autopsy.datamodel.accounts.Accounts;
|
||||
import org.sleuthkit.datamodel.Account;
|
||||
@ -33,7 +34,8 @@ class Utils {
|
||||
}
|
||||
|
||||
static ZoneId getUserPreferredZoneId() {
|
||||
ZoneId zone = UserPreferences.displayTimesInLocalTime() ? ZoneOffset.systemDefault() : ZoneOffset.UTC;
|
||||
ZoneId zone = UserPreferences.displayTimesInLocalTime() ?
|
||||
ZoneOffset.systemDefault() : TimeZone.getTimeZone(UserPreferences.getTimeZoneForDisplays()).toZoneId();
|
||||
return zone;
|
||||
}
|
||||
|
||||
|
@ -424,7 +424,7 @@ class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer {
|
||||
|
||||
try (Statement statement = connection.createStatement();
|
||||
ResultSet resultSet = statement.executeQuery(
|
||||
"SELECT count (*) as count FROM " + "\"" + tableName + "\"")) { //NON-NLS{
|
||||
"SELECT count (*) as count FROM " + "\"" + tableName + "\"")) { //NON-NLS
|
||||
|
||||
numRows = resultSet.getInt("count");
|
||||
numEntriesField.setText(numRows + " entries");
|
||||
@ -442,9 +442,23 @@ class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer {
|
||||
} else {
|
||||
exportCsvButton.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) {
|
||||
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));
|
||||
|
@ -24,6 +24,7 @@ import org.sleuthkit.autopsy.events.MessageServiceConnectionInfo;
|
||||
import java.util.prefs.PreferenceChangeListener;
|
||||
import java.util.prefs.Preferences;
|
||||
import org.openide.util.NbPreferences;
|
||||
import org.python.icu.util.TimeZone;
|
||||
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
|
||||
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
||||
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_VIEWS_TREE = "HideSlackFilesInViewsTree"; //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 IS_MULTI_USER_MODE_ENABLED = "IsMultiUserModeEnabled"; //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);
|
||||
}
|
||||
|
||||
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() {
|
||||
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.text=Stay on the same file viewer
|
||||
ViewPreferencesPanel.useLocalTimeRadioButton.text=Use local time zone
|
||||
ViewPreferencesPanel.useGMTTimeRadioButton.text=Use GMT
|
||||
ViewPreferencesPanel.dataSourcesHideKnownCheckbox.text=Data Sources area (the directory hierarchy)
|
||||
ViewPreferencesPanel.viewsHideKnownCheckbox.text=Views area
|
||||
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.deletedFilesLimitCheckbox.text=Limit to 10,000
|
||||
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.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.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.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_INTERESTING_FILE_HIT.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;
|
||||
} else {
|
||||
return 6;
|
||||
|
@ -40,6 +40,7 @@ public final class TextPrompt extends JLabel
|
||||
|
||||
public TextPrompt(String text, JTextComponent component, Show show) {
|
||||
this.component = component;
|
||||
component.removeAll();
|
||||
setShow(show);
|
||||
document = component.getDocument();
|
||||
|
||||
|
@ -31,11 +31,19 @@
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="null"/>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[625, 452]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<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>
|
||||
<DimensionLayout dim="0">
|
||||
@ -87,57 +95,68 @@
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="commentsOccurencesColumnsCheckbox" 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 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="103" groupAlignment="0" attributes="0">
|
||||
<Component id="hideKnownFilesLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" alignment="0" groupAlignment="1" attributes="0">
|
||||
<Group type="103" alignment="1" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="dataSourcesHideSlackCheckbox" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="viewsHideSlackCheckbox" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="hideKnownFilesLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" alignment="0" groupAlignment="1" attributes="0">
|
||||
<Group type="103" alignment="1" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="dataSourcesHideSlackCheckbox" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="viewsHideSlackCheckbox" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<Component id="hideSlackFilesLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="dataSourcesHideKnownCheckbox" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="viewsHideKnownCheckbox" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
<Component id="hideSlackFilesLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="dataSourcesHideKnownCheckbox" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="viewsHideKnownCheckbox" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="displayTimeLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" 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="useGMTTimeRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="useLocalTimeRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="displayTimeLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" 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="useLocalTimeRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="useAnotherTimeRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<Component id="selectFileLabel" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<Component id="selectFileLabel" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="hideOtherUsersTagsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="deletedFilesLimitLabel" alignment="0" min="-2" pref="215" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<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"/>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="10" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -158,6 +177,16 @@
|
||||
<Component id="dataSourcesHideSlackCheckbox" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace 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 type="102" alignment="0" attributes="0">
|
||||
<Component id="selectFileLabel" min="-2" max="-2" attributes="0"/>
|
||||
@ -169,20 +198,12 @@
|
||||
<Component id="displayTimeLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="useLocalTimeRadioButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="useGMTTimeRadioButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace 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>
|
||||
<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"/>
|
||||
<Component id="deletedFilesLimitCheckbox" min="-2" pref="33" 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"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JRadioButton" name="useGMTTimeRadioButton">
|
||||
<Component class="javax.swing.JRadioButton" name="useAnotherTimeRadioButton">
|
||||
<Properties>
|
||||
<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>
|
||||
</Properties>
|
||||
<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>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="hideOtherUsersTagsCheckbox">
|
||||
@ -356,6 +377,28 @@
|
||||
</Property>
|
||||
</Properties>
|
||||
</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>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="currentCaseSettingsPanel">
|
||||
|
@ -19,12 +19,14 @@
|
||||
package org.sleuthkit.autopsy.corecomponents;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.TimeZone;
|
||||
import javax.swing.JPanel;
|
||||
import org.netbeans.spi.options.OptionsPanelController;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.CasePreferences;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbUtil;
|
||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||
import org.sleuthkit.autopsy.coreutils.TimeZoneUtils;
|
||||
import org.sleuthkit.autopsy.deletedFiles.DeletedFilePreferences;
|
||||
import org.sleuthkit.autopsy.directorytree.DirectoryTreeTopComponent;
|
||||
|
||||
@ -44,6 +46,8 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
||||
public ViewPreferencesPanel(boolean immediateUpdates) {
|
||||
initComponents();
|
||||
this.immediateUpdates = immediateUpdates;
|
||||
|
||||
this.timeZoneList.setListData(TimeZoneUtils.createTimeZoneList().stream().toArray(String[]::new));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -54,8 +58,10 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
||||
useBestViewerRadioButton.setSelected(!keepPreferredViewer);
|
||||
|
||||
boolean useLocalTime = UserPreferences.displayTimesInLocalTime();
|
||||
timeZoneList.setEnabled(!useLocalTime);
|
||||
timeZoneList.setSelectedValue(TimeZoneUtils.createTimeZoneString(TimeZone.getTimeZone(UserPreferences.getTimeZoneForDisplays())), true);
|
||||
useLocalTimeRadioButton.setSelected(useLocalTime);
|
||||
useGMTTimeRadioButton.setSelected(!useLocalTime);
|
||||
useAnotherTimeRadioButton.setSelected(!useLocalTime);
|
||||
|
||||
dataSourcesHideKnownCheckbox.setSelected(UserPreferences.hideKnownFilesInDataSourcesTree());
|
||||
viewsHideKnownCheckbox.setSelected(UserPreferences.hideKnownFilesInViewsTree());
|
||||
@ -84,6 +90,9 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
||||
public void store() {
|
||||
UserPreferences.setKeepPreferredContentViewer(keepCurrentViewerRadioButton.isSelected());
|
||||
UserPreferences.setDisplayTimesInLocalTime(useLocalTimeRadioButton.isSelected());
|
||||
if (useAnotherTimeRadioButton.isSelected()) {
|
||||
UserPreferences.setTimeZoneForDisplays(timeZoneList.getSelectedValue().substring(11).trim());
|
||||
}
|
||||
UserPreferences.setHideKnownFilesInDataSourcesTree(dataSourcesHideKnownCheckbox.isSelected());
|
||||
UserPreferences.setHideKnownFilesInViewsTree(viewsHideKnownCheckbox.isSelected());
|
||||
UserPreferences.setHideSlackFilesInDataSourcesTree(dataSourcesHideSlackCheckbox.isSelected());
|
||||
@ -135,19 +144,24 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
||||
viewsHideSlackCheckbox = new javax.swing.JCheckBox();
|
||||
displayTimeLabel = new javax.swing.JLabel();
|
||||
useLocalTimeRadioButton = new javax.swing.JRadioButton();
|
||||
useGMTTimeRadioButton = new javax.swing.JRadioButton();
|
||||
useAnotherTimeRadioButton = new javax.swing.JRadioButton();
|
||||
hideOtherUsersTagsCheckbox = new javax.swing.JCheckBox();
|
||||
hideOtherUsersTagsLabel = new javax.swing.JLabel();
|
||||
commentsOccurencesColumnsCheckbox = new javax.swing.JCheckBox();
|
||||
centralRepoLabel = new javax.swing.JLabel();
|
||||
deletedFilesLimitCheckbox = new javax.swing.JCheckBox();
|
||||
deletedFilesLimitLabel = new javax.swing.JLabel();
|
||||
jScrollPane1 = new javax.swing.JScrollPane();
|
||||
timeZoneList = new javax.swing.JList<>();
|
||||
currentCaseSettingsPanel = new javax.swing.JPanel();
|
||||
groupByDataSourceCheckbox = new javax.swing.JCheckBox();
|
||||
currentSessionSettingsPanel = new javax.swing.JPanel();
|
||||
hideRejectedResultsCheckbox = new javax.swing.JCheckBox();
|
||||
|
||||
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
|
||||
|
||||
@ -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
|
||||
useGMTTimeRadioButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
org.openide.awt.Mnemonics.setLocalizedText(useAnotherTimeRadioButton, org.openide.util.NbBundle.getMessage(ViewPreferencesPanel.class, "ViewPreferencesPanel.useAnotherTimeRadioButton.text")); // NOI18N
|
||||
useAnotherTimeRadioButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
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
|
||||
|
||||
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);
|
||||
globalSettingsPanel.setLayout(globalSettingsPanelLayout);
|
||||
globalSettingsPanelLayout.setHorizontalGroup(
|
||||
@ -256,41 +277,48 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
||||
.addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(commentsOccurencesColumnsCheckbox)
|
||||
.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.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(hideKnownFilesLabel)
|
||||
.addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addGroup(globalSettingsPanelLayout.createSequentialGroup()
|
||||
.addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(hideKnownFilesLabel)
|
||||
.addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(globalSettingsPanelLayout.createSequentialGroup()
|
||||
.addGap(10, 10, 10)
|
||||
.addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(dataSourcesHideSlackCheckbox)
|
||||
.addComponent(viewsHideSlackCheckbox)))
|
||||
.addComponent(hideSlackFilesLabel))
|
||||
.addGroup(globalSettingsPanelLayout.createSequentialGroup()
|
||||
.addGap(10, 10, 10)
|
||||
.addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(dataSourcesHideKnownCheckbox)
|
||||
.addComponent(viewsHideKnownCheckbox)))))
|
||||
.addGap(18, 18, 18)
|
||||
.addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(displayTimeLabel)
|
||||
.addGroup(globalSettingsPanelLayout.createSequentialGroup()
|
||||
.addGap(10, 10, 10)
|
||||
.addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(dataSourcesHideSlackCheckbox)
|
||||
.addComponent(viewsHideSlackCheckbox)))
|
||||
.addComponent(hideSlackFilesLabel))
|
||||
.addGroup(globalSettingsPanelLayout.createSequentialGroup()
|
||||
.addGap(10, 10, 10)
|
||||
.addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(dataSourcesHideKnownCheckbox)
|
||||
.addComponent(viewsHideKnownCheckbox)))))
|
||||
.addGap(18, 18, 18)
|
||||
.addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(displayTimeLabel)
|
||||
.addGroup(globalSettingsPanelLayout.createSequentialGroup()
|
||||
.addGap(10, 10, 10)
|
||||
.addGroup(globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(keepCurrentViewerRadioButton)
|
||||
.addComponent(useBestViewerRadioButton)
|
||||
.addComponent(useGMTTimeRadioButton)
|
||||
.addComponent(useLocalTimeRadioButton)))
|
||||
.addComponent(selectFileLabel)))
|
||||
.addComponent(hideOtherUsersTagsLabel)
|
||||
.addComponent(centralRepoLabel)
|
||||
.addComponent(deletedFilesLimitLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 215, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGap(0, 10, Short.MAX_VALUE)))
|
||||
.addContainerGap())
|
||||
.addComponent(keepCurrentViewerRadioButton)
|
||||
.addComponent(useBestViewerRadioButton)
|
||||
.addComponent(useLocalTimeRadioButton)
|
||||
.addComponent(useAnotherTimeRadioButton)))
|
||||
.addComponent(selectFileLabel)))
|
||||
.addComponent(hideOtherUsersTagsLabel)
|
||||
.addComponent(deletedFilesLimitLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 215, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGap(0, 0, Short.MAX_VALUE)))
|
||||
.addContainerGap())))
|
||||
);
|
||||
globalSettingsPanelLayout.setVerticalGroup(
|
||||
globalSettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
@ -308,7 +336,17 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(dataSourcesHideSlackCheckbox)
|
||||
.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()
|
||||
.addComponent(selectFileLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
@ -320,17 +358,9 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(useLocalTimeRadioButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(useGMTTimeRadioButton)))
|
||||
.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)
|
||||
.addComponent(useAnotherTimeRadioButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 67, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(deletedFilesLimitCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, 33, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(0, 0, 0))
|
||||
@ -415,11 +445,11 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
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.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
|
||||
|
||||
@ -445,7 +475,8 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
||||
|
||||
private void useLocalTimeRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_useLocalTimeRadioButtonActionPerformed
|
||||
useLocalTimeRadioButton.setSelected(true);
|
||||
useGMTTimeRadioButton.setSelected(false);
|
||||
useAnotherTimeRadioButton.setSelected(false);
|
||||
timeZoneList.setEnabled(false);
|
||||
if (immediateUpdates) {
|
||||
UserPreferences.setDisplayTimesInLocalTime(true);
|
||||
} else {
|
||||
@ -453,15 +484,16 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
||||
}
|
||||
}//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);
|
||||
useGMTTimeRadioButton.setSelected(true);
|
||||
useAnotherTimeRadioButton.setSelected(true);
|
||||
timeZoneList.setEnabled(true);
|
||||
if (immediateUpdates) {
|
||||
UserPreferences.setDisplayTimesInLocalTime(false);
|
||||
} else {
|
||||
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
|
||||
if (immediateUpdates) {
|
||||
@ -535,6 +567,14 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
||||
}
|
||||
}//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
|
||||
private javax.swing.JLabel centralRepoLabel;
|
||||
@ -553,10 +593,12 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
|
||||
private javax.swing.JLabel hideOtherUsersTagsLabel;
|
||||
private javax.swing.JCheckBox hideRejectedResultsCheckbox;
|
||||
private javax.swing.JLabel hideSlackFilesLabel;
|
||||
private javax.swing.JScrollPane jScrollPane1;
|
||||
private javax.swing.JRadioButton keepCurrentViewerRadioButton;
|
||||
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 useGMTTimeRadioButton;
|
||||
private javax.swing.JRadioButton useLocalTimeRadioButton;
|
||||
private javax.swing.JPanel viewPreferencesPanel;
|
||||
private javax.swing.JScrollPane viewPreferencesScrollPane;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2012-2015 Basis Technology Corp.
|
||||
* Copyright 2012-2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -18,14 +18,22 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.coreutils;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
public class NetworkUtils {
|
||||
|
||||
private NetworkUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the host name variable. Sometimes the network can be finicky, so the
|
||||
* answer returned by getHostName() could throw an exception or be null.
|
||||
* Have it read the environment variable if getHostName() is unsuccessful.
|
||||
*
|
||||
* @return the local host name
|
||||
*/
|
||||
public static String getLocalHostName() {
|
||||
String hostName = "";
|
||||
@ -41,4 +49,78 @@ public class NetworkUtils {
|
||||
}
|
||||
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
|
||||
*
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Copyright 2011-2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.List;
|
||||
import java.util.SimpleTimeZone;
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* Utility methods for workig with time zones.
|
||||
@ -41,7 +47,7 @@ public class TimeZoneUtils {
|
||||
java.util.TimeZone zone = java.util.TimeZone.getTimeZone(timeZoneId);
|
||||
int offset = zone.getRawOffset() / 1000;
|
||||
int hour = offset / 3600;
|
||||
int min = (offset % 3600) / 60;
|
||||
int min = Math.abs((offset % 3600) / 60);
|
||||
|
||||
DateFormat dfm = new SimpleDateFormat("z");
|
||||
dfm.setTimeZone(zone);
|
||||
@ -60,6 +66,73 @@ public class TimeZoneUtils {
|
||||
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.
|
||||
*/
|
||||
|
@ -145,7 +145,7 @@ public final class ContentUtils {
|
||||
|
||||
try {
|
||||
if (!shouldDisplayTimesInLocalTime()) {
|
||||
return TimeZone.getTimeZone("GMT");
|
||||
return TimeZone.getTimeZone(UserPreferences.getTimeZoneForDisplays());
|
||||
} else {
|
||||
final Content dataSource = content.getDataSource();
|
||||
if ((dataSource != null) && (dataSource instanceof Image)) {
|
||||
|
@ -20,8 +20,7 @@ package org.sleuthkit.autopsy.datasourceprocessors;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Calendar;
|
||||
import java.util.SimpleTimeZone;
|
||||
import java.util.TimeZone;
|
||||
import java.util.List;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JPanel;
|
||||
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.coreutils.ModuleSettings;
|
||||
import org.sleuthkit.autopsy.coreutils.PathValidator;
|
||||
import org.sleuthkit.autopsy.coreutils.TimeZoneUtils;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
private void createTimeZoneList() {
|
||||
// load and add all timezone
|
||||
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);
|
||||
|
||||
timeZoneComboBox.addItem(item);
|
||||
List<String> timeZoneList = TimeZoneUtils.createTimeZoneList();
|
||||
for (String timeZone : timeZoneList) {
|
||||
timeZoneComboBox.addItem(timeZone);
|
||||
}
|
||||
// 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
|
||||
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) {
|
||||
switch (evt.getKey()) {
|
||||
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_SLACK_FILES_IN_DATA_SRCS_TREE:
|
||||
case UserPreferences.HIDE_CENTRAL_REPO_COMMENTS_AND_OCCURRENCES:
|
||||
|
@ -29,7 +29,6 @@ import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.SimpleTimeZone;
|
||||
@ -44,6 +43,7 @@ import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.coreutils.TimeZoneUtils;
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
||||
Set<TimeZone> caseTimeZones = currentCase.getTimeZones();
|
||||
Iterator<TimeZone> iterator = caseTimeZones.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
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);
|
||||
for (TimeZone timeZone : caseTimeZones) {
|
||||
timeZones.add(TimeZoneUtils.createTimeZoneString(timeZone));
|
||||
}
|
||||
|
||||
if (caseTimeZones.size() > 0) {
|
||||
timeZones.add(SEPARATOR);
|
||||
}
|
||||
|
||||
// load and add all timezone
|
||||
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);
|
||||
}
|
||||
timeZones.addAll(TimeZoneUtils.createTimeZoneList());
|
||||
} catch (NoCurrentCaseException ex) {
|
||||
// No current case.
|
||||
}
|
||||
|
@ -269,8 +269,7 @@ class MSOfficeEmbeddedContentExtractor {
|
||||
HWPFDocument doc = new HWPFDocument(new ReadContentInputStream(af));
|
||||
PicturesTable pictureTable = doc.getPicturesTable();
|
||||
listOfAllPictures = pictureTable.getAllPictures();
|
||||
} catch (IOException | IllegalArgumentException
|
||||
| IndexOutOfBoundsException | NullPointerException ex) {
|
||||
} catch (Exception ex) {
|
||||
// IOException:
|
||||
// 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
|
||||
// likely due to problems with the file formats that POI is poorly
|
||||
// handling.
|
||||
return null;
|
||||
} catch (Throwable ex) {
|
||||
// instantiating POI containers throw RuntimeExceptions
|
||||
LOGGER.log(Level.SEVERE, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.docContainer.init.err", af.getName()), ex); //NON-NLS
|
||||
|
||||
//Any runtime exception escaping
|
||||
LOGGER.log(Level.WARNING, "Word document container could not be initialized. Reason: {0}", ex.getMessage()); //NON-NLS
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -333,8 +331,7 @@ class MSOfficeEmbeddedContentExtractor {
|
||||
try {
|
||||
HSLFSlideShow ppt = new HSLFSlideShow(new ReadContentInputStream(af));
|
||||
listOfAllPictures = ppt.getPictureData();
|
||||
} catch (IOException | IllegalArgumentException
|
||||
| IndexOutOfBoundsException ex) {
|
||||
} catch (Exception ex) {
|
||||
// IllegalArgumentException:
|
||||
// This will catch OldFileFormatException, which is thrown when the
|
||||
// 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
|
||||
// likely due to problems with the file formats that POI is poorly
|
||||
// handling.
|
||||
return null;
|
||||
} 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
|
||||
LOGGER.log(Level.WARNING, "PPT container could not be initialized. Reason: {0}", ex.getMessage()); //NON-NLS
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -422,9 +416,7 @@ class MSOfficeEmbeddedContentExtractor {
|
||||
try {
|
||||
Workbook xls = new HSSFWorkbook(new ReadContentInputStream(af));
|
||||
listOfAllPictures = xls.getAllPictures();
|
||||
} catch (IOException | LeftoverDataException
|
||||
| RecordFormatException | IllegalArgumentException
|
||||
| IndexOutOfBoundsException ex) {
|
||||
} catch (Exception ex) {
|
||||
// IllegalArgumentException:
|
||||
// This will catch OldFileFormatException, which is thrown when the
|
||||
// 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
|
||||
// likely due to problems with the file formats that POI is poorly
|
||||
// handling.
|
||||
return null;
|
||||
} 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
|
||||
LOGGER.log(Level.WARNING, "Excel (.xls) document container could not be initialized. Reason: {0}", ex.getMessage()); //NON-NLS
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -180,6 +180,15 @@ class SevenZipExtractor {
|
||||
* @return true if potential zip bomb, false otherwise
|
||||
*/
|
||||
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 {
|
||||
final Long archiveItemSize = (Long) inArchive.getProperty(
|
||||
inArchiveItemIndex, PropID.SIZE);
|
||||
@ -540,7 +549,6 @@ class SevenZipExtractor {
|
||||
inArchive = SevenZip.openInArchive(options, stream, password);
|
||||
}
|
||||
numItems = inArchive.getNumberOfItems();
|
||||
logger.log(Level.INFO, "Count of items in archive: {0}: {1}", new Object[]{escapedArchiveFilePath, numItems}); //NON-NLS
|
||||
progress.start(numItems);
|
||||
progressStarted = true;
|
||||
|
||||
|
@ -28,6 +28,7 @@ import com.healthmarketscience.jackcess.util.MemFileChannel;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.BufferUnderflowException;
|
||||
import java.util.logging.Level;
|
||||
import org.apache.tika.exception.EncryptedDocumentException;
|
||||
import org.apache.tika.exception.TikaException;
|
||||
@ -313,7 +314,12 @@ final class EncryptionDetectionFileIngestModule extends FileIngestModuleAdapter
|
||||
DatabaseBuilder databaseBuilder = new DatabaseBuilder();
|
||||
databaseBuilder.setChannel(memFileChannel);
|
||||
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
|
||||
* 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.moduleDescription.text=Identifies known and notable files using supplied hash sets, such as a standard NSRL hash set.
|
||||
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.settingKnownBadStateErr=Error encountered while setting notable state 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(
|
||||
HashLookupModuleFactory.getModuleName(),
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -649,6 +649,15 @@ public final class FilesSet implements Serializable {
|
||||
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.
|
||||
*
|
||||
@ -820,11 +829,11 @@ public final class FilesSet implements Serializable {
|
||||
*
|
||||
* @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
|
||||
// AbstractFile.getFileNameExtension() returns just the
|
||||
// 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.
|
||||
*/
|
||||
|
@ -29,7 +29,7 @@
|
||||
<Layout>
|
||||
<DimensionLayout dim="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>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
@ -173,7 +173,7 @@
|
||||
<Component id="deleteRuleButton" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="24" pref="47" max="32767" attributes="0"/>
|
||||
<EmptySpace min="24" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
|
@ -960,7 +960,7 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
|
||||
.addComponent(editRuleButton)
|
||||
.addGap(18, 18, 18)
|
||||
.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});
|
||||
@ -1060,7 +1060,7 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jScrollPane1)
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 800, Short.MAX_VALUE)
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
|
@ -47,22 +47,23 @@
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="ruleNameTextField" max="32767" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="daysIncludedTextField" min="-2" pref="69" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="daysIncludedLabel" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<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"/>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="1" max="-2" attributes="0"/>
|
||||
</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>
|
||||
<Component id="jLabel5" min="-2" max="-2" attributes="0"/>
|
||||
@ -205,6 +206,9 @@
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="fullNameRadioButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JRadioButton" name="extensionRadioButton">
|
||||
<Properties>
|
||||
@ -216,6 +220,9 @@
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="extensionRadioButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="nameRegexCheckbox">
|
||||
<Properties>
|
||||
|
@ -18,7 +18,9 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.modules.interestingitems;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.SortedSet;
|
||||
import java.util.logging.Level;
|
||||
@ -31,6 +33,7 @@ import org.openide.DialogDisplayer;
|
||||
import org.openide.NotifyDescriptor;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.autopsy.corecomponents.TextPrompt;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector;
|
||||
import org.sleuthkit.autopsy.modules.interestingitems.FilesSetDefsPanel.PANEL_TYPE;
|
||||
@ -46,6 +49,8 @@ final class FilesSetRulePanel extends javax.swing.JPanel {
|
||||
"FilesSetRulePanel.kiloBytes=Kilobytes",
|
||||
"FilesSetRulePanel.megaBytes=Megabytes",
|
||||
"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.NoMimeTypeError=Please select a valid MIME type.",
|
||||
"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 JButton okButton;
|
||||
private JButton cancelButton;
|
||||
private TextPrompt nameTextFieldPrompt;
|
||||
|
||||
/**
|
||||
* Constructs a files set rule panel in create rule mode.
|
||||
@ -87,6 +93,8 @@ final class FilesSetRulePanel extends javax.swing.JPanel {
|
||||
this.dateCheckActionPerformed(null);
|
||||
populateComponentsWithDefaultValues();
|
||||
this.setButtons(okButton, cancelButton);
|
||||
|
||||
updateNameTextFieldPrompt();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -120,6 +128,34 @@ final class FilesSetRulePanel extends javax.swing.JPanel {
|
||||
populatePathConditionComponents(rule);
|
||||
populateDateConditionComponents(rule);
|
||||
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.nameRegexCheckbox.isSelected()) {
|
||||
try {
|
||||
Pattern pattern = Pattern.compile(this.nameTextField.getText());
|
||||
Pattern pattern = Pattern.compile(this.nameTextField.getText(), Pattern.CASE_INSENSITIVE);
|
||||
if (this.fullNameRadioButton.isSelected()) {
|
||||
condition = new FilesSet.Rule.FullNameCondition(pattern);
|
||||
} else {
|
||||
@ -449,7 +485,7 @@ final class FilesSetRulePanel extends javax.swing.JPanel {
|
||||
if (this.fullNameRadioButton.isSelected()) {
|
||||
condition = new FilesSet.Rule.FullNameCondition(this.nameTextField.getText());
|
||||
} else {
|
||||
condition = new FilesSet.Rule.ExtensionCondition(this.nameTextField.getText());
|
||||
condition = new FilesSet.Rule.ExtensionCondition(Arrays.asList(this.nameTextField.getText().split(",")));
|
||||
}
|
||||
} else {
|
||||
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.pathRegexCheckBox.isSelected()) {
|
||||
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) {
|
||||
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
|
||||
@ -657,10 +693,20 @@ final class FilesSetRulePanel extends javax.swing.JPanel {
|
||||
nameButtonGroup.add(fullNameRadioButton);
|
||||
org.openide.awt.Mnemonics.setLocalizedText(fullNameRadioButton, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.fullNameRadioButton.text")); // NOI18N
|
||||
fullNameRadioButton.setEnabled(false);
|
||||
fullNameRadioButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
fullNameRadioButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
nameButtonGroup.add(extensionRadioButton);
|
||||
org.openide.awt.Mnemonics.setLocalizedText(extensionRadioButton, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.extensionRadioButton.text")); // NOI18N
|
||||
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
|
||||
nameRegexCheckbox.setEnabled(false);
|
||||
@ -782,18 +828,19 @@ final class FilesSetRulePanel extends javax.swing.JPanel {
|
||||
.addComponent(pathSeparatorInfoLabel))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(ruleNameTextField)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(daysIncludedTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 69, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(daysIncludedLabel))
|
||||
.addComponent(ruleNameTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 249, Short.MAX_VALUE)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(fullNameRadioButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(extensionRadioButton, javax.swing.GroupLayout.PREFERRED_SIZE, 98, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(nameRegexCheckbox)))
|
||||
.addGap(1, 1, 1))))
|
||||
.addComponent(daysIncludedLabel)
|
||||
.addGap(0, 0, Short.MAX_VALUE)))
|
||||
.addGap(1, 1, 1))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(fullNameRadioButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(extensionRadioButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(nameRegexCheckbox))))
|
||||
.addComponent(jLabel5)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
@ -952,6 +999,14 @@ final class FilesSetRulePanel extends javax.swing.JPanel {
|
||||
this.setOkButton();
|
||||
}//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
|
||||
private javax.swing.JRadioButton allRadioButton;
|
||||
private javax.swing.JCheckBox dateCheck;
|
||||
|
@ -25,6 +25,7 @@ import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -280,7 +281,7 @@ class InterestingItemsFilesSetSettings implements Serializable {
|
||||
if (elem.getTagName().equals(NAME_RULE_TAG)) {
|
||||
nameCondition = new FilesSet.Rule.FullNameCondition(content);
|
||||
} 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.coreutils.TimeStampUtils;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.DataSource;
|
||||
|
||||
/*
|
||||
* A runnable that adds an archive data source as well as data sources contained
|
||||
@ -195,10 +196,19 @@ class AddArchiveTask implements Runnable {
|
||||
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;
|
||||
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
|
||||
break;
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
|
||||
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.NetworkUtils;
|
||||
import org.sleuthkit.autopsy.coreutils.StopWatch;
|
||||
import org.sleuthkit.autopsy.events.AutopsyEventException;
|
||||
import org.sleuthkit.autopsy.events.AutopsyEventPublisher;
|
||||
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.
|
||||
*/
|
||||
CaseDeletionResult deleteCase(AutoIngestJob job) {
|
||||
String caseName = job.getManifest().getCaseName();
|
||||
Path caseDirectoryPath = job.getCaseDirectoryPath();
|
||||
Path metadataFilePath = caseDirectoryPath.resolve(caseName + CaseMetadata.getFileExtension());
|
||||
StopWatch stopWatch = new StopWatch();
|
||||
stopWatch.start();
|
||||
synchronized (jobsLock) {
|
||||
String caseName = job.getManifest().getCaseName();
|
||||
Path metadataFilePath = job.getCaseDirectoryPath().resolve(caseName + CaseMetadata.getFileExtension());
|
||||
|
||||
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 {
|
||||
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);
|
||||
|
||||
} 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;
|
||||
} 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;
|
||||
}
|
||||
|
||||
// Update the state of completed jobs associated with this case to indicate
|
||||
// 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())) {
|
||||
try {
|
||||
completedJob.setProcessingStatus(DELETED);
|
||||
AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(completedJob);
|
||||
coordinationService.setNodeData(CoordinationService.CategoryNode.MANIFESTS, completedJob.getManifest().getFilePath().toString(), nodeData.toArray());
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
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.
|
||||
jobsSnapshot.completedJobs.removeIf((AutoIngestJob completedJob)
|
||||
stopWatch.reset();
|
||||
stopWatch.start();
|
||||
completedJobs.removeIf((AutoIngestJob completedJob)
|
||||
-> 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.
|
||||
stopWatch.reset();
|
||||
stopWatch.start();
|
||||
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;
|
||||
|
@ -25,9 +25,7 @@ import java.util.Calendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.SimpleTimeZone;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TimeZone;
|
||||
import java.util.TreeSet;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JPanel;
|
||||
@ -43,6 +41,7 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
||||
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
|
||||
import org.sleuthkit.autopsy.coreutils.PathValidator;
|
||||
import org.sleuthkit.autopsy.coreutils.TimeZoneUtils;
|
||||
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
final class MemoryDSInputPanel extends JPanel implements DocumentListener {
|
||||
@ -132,26 +131,13 @@ final class MemoryDSInputPanel extends JPanel implements DocumentListener {
|
||||
* machine time zone to be selected.
|
||||
*/
|
||||
private void createTimeZoneList() {
|
||||
// load and add all timezone
|
||||
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);
|
||||
|
||||
timeZoneComboBox.addItem(item);
|
||||
List<String> timeZoneList = TimeZoneUtils.createTimeZoneList();
|
||||
for (String timeZone : timeZoneList) {
|
||||
timeZoneComboBox.addItem(timeZone);
|
||||
}
|
||||
// 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
|
||||
timeZoneComboBox.setSelectedItem(formatted);
|
||||
timeZoneComboBox.setSelectedItem(TimeZoneUtils.createTimeZoneString(Calendar.getInstance().getTimeZone()));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
Manifest-Version: 1.0
|
||||
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-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
|
||||
* mimetype could not be detected.
|
||||
*/
|
||||
static boolean hasDrawableMIMEType(AbstractFile file) throws FileTypeDetector.FileTypeDetectorInitException {
|
||||
String mimeType = getFileTypeDetector().getMIMEType(file).toLowerCase();
|
||||
static boolean hasDrawableMIMEType(AbstractFile file) {
|
||||
String mimeType = file.getMIMEType();
|
||||
if (mimeType == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mimeType = mimeType.toLowerCase();
|
||||
return isDrawableMimeType(mimeType) || (mimeType.equals("audio/x-aiff") && "tiff".equalsIgnoreCase(file.getNameExtension()));
|
||||
}
|
||||
|
||||
@ -234,13 +239,13 @@ public enum FileTypeUtils {
|
||||
* available, a video extension.
|
||||
*/
|
||||
public static boolean hasVideoMIMEType(AbstractFile file) {
|
||||
try {
|
||||
String mimeType = getFileTypeDetector().getMIMEType(file).toLowerCase();
|
||||
return mimeType.startsWith("video/") || videoMimeTypes.contains(mimeType);
|
||||
} catch (FileTypeDetector.FileTypeDetectorInitException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error determining MIME type of " + getContentPathSafe(file), ex);
|
||||
String mimeType = file.getMIMEType();
|
||||
if (mimeType == null) {
|
||||
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.GroupViewState;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.DataSource;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
@ -253,6 +252,7 @@ public final class ImageGalleryController {
|
||||
|
||||
/**
|
||||
* Should the "forward" button on the history be enabled?
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public ReadOnlyBooleanProperty getCanAdvance() {
|
||||
@ -261,6 +261,7 @@ public final class ImageGalleryController {
|
||||
|
||||
/**
|
||||
* Should the "Back" button on the history be enabled?
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public ReadOnlyBooleanProperty getCanRetreat() {
|
||||
@ -268,10 +269,9 @@ public final class ImageGalleryController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the passed in group. Causes this group to
|
||||
* get recorded in the history queue and observers of the
|
||||
* current state will be notified and update their panels/widgets
|
||||
* appropriately.
|
||||
* Display the passed in group. Causes this group to get recorded in the
|
||||
* history queue and observers of the current state will be notified and
|
||||
* update their panels/widgets appropriately.
|
||||
*
|
||||
* @param newState
|
||||
*/
|
||||
@ -282,6 +282,7 @@ public final class ImageGalleryController {
|
||||
|
||||
/**
|
||||
* Display the next group in the "forward" history stack
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public GroupViewState advance() {
|
||||
@ -290,6 +291,7 @@ public final class ImageGalleryController {
|
||||
|
||||
/**
|
||||
* Display the previous group in the "back" history stack
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public GroupViewState retreat() {
|
||||
@ -433,10 +435,6 @@ public final class ImageGalleryController {
|
||||
return drawableDB.getFileFromID(fileID);
|
||||
}
|
||||
|
||||
public ReadOnlyDoubleProperty regroupProgress() {
|
||||
return groupManager.regroupProgress();
|
||||
}
|
||||
|
||||
public HashSetManager getHashSetManager() {
|
||||
return hashSetManager;
|
||||
}
|
||||
@ -696,8 +694,17 @@ public final class ImageGalleryController {
|
||||
// Cycle through all of the files returned and call processFile on each
|
||||
//do in transaction
|
||||
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) {
|
||||
if (caseDbTransaction == null) {
|
||||
caseDbTransaction = tskCase.beginTransaction();
|
||||
}
|
||||
|
||||
if (isCancelled() || Thread.interrupted()) {
|
||||
logger.log(Level.WARNING, "Task cancelled or interrupted: not all contents may be transfered to drawable database."); //NON-NLS
|
||||
taskCompletionStatus = false;
|
||||
@ -712,6 +719,14 @@ public final class ImageGalleryController {
|
||||
progressHandle.progress(f.getName(), workDone);
|
||||
updateProgress(workDone - 1 / (double) files.size());
|
||||
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();
|
||||
@ -720,13 +735,16 @@ public final class ImageGalleryController {
|
||||
updateProgress(1.0);
|
||||
|
||||
progressHandle.start();
|
||||
caseDbTransaction.commit();
|
||||
caseDbTransaction = null;
|
||||
if (caseDbTransaction != null) {
|
||||
caseDbTransaction.commit();
|
||||
caseDbTransaction = null;
|
||||
}
|
||||
|
||||
// pass true so that groupmanager is notified of the changes
|
||||
taskDB.commitTransaction(drawableDbTransaction, true);
|
||||
drawableDbTransaction = null;
|
||||
|
||||
} catch (TskCoreException ex) {
|
||||
} catch (TskCoreException | InterruptedException ex) {
|
||||
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
|
||||
MessageNotifyUtil.Notify.warn(Bundle.BulkTask_errPopulating_errMsg(), ex.getMessage());
|
||||
@ -792,20 +810,16 @@ public final class ImageGalleryController {
|
||||
if (known) {
|
||||
taskDB.removeFile(f.getId(), tr); //remove known files
|
||||
} else {
|
||||
try {
|
||||
// if mimetype of the file hasn't been ascertained, ingest might not have completed yet.
|
||||
if (null == f.getMIMEType()) {
|
||||
// set to false to force the DB to be marked as stale
|
||||
this.setTaskCompletionStatus(false);
|
||||
} //supported mimetype => analyzed
|
||||
else if (FileTypeUtils.hasDrawableMIMEType(f)) {
|
||||
taskDB.updateFile(DrawableFile.create(f, true, false), tr, caseDbTransaction);
|
||||
} //unsupported mimtype => analyzed but shouldn't include
|
||||
else {
|
||||
taskDB.removeFile(f.getId(), tr);
|
||||
}
|
||||
} catch (FileTypeDetector.FileTypeDetectorInitException ex) {
|
||||
throw new TskCoreException("Failed to initialize FileTypeDetector.", ex);
|
||||
// if mimetype of the file hasn't been ascertained, ingest might not have completed yet.
|
||||
if (null == f.getMIMEType()) {
|
||||
// set to false to force the DB to be marked as stale
|
||||
this.setTaskCompletionStatus(false);
|
||||
} //supported mimetype => analyzed
|
||||
else if (FileTypeUtils.hasDrawableMIMEType(f)) {
|
||||
taskDB.updateFile(DrawableFile.create(f, true, false), tr, caseDbTransaction);
|
||||
} //unsupported mimtype => analyzed but shouldn't include
|
||||
else {
|
||||
taskDB.removeFile(f.getId(), tr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -840,7 +854,7 @@ public final class ImageGalleryController {
|
||||
|
||||
@Override
|
||||
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
|
||||
|
@ -208,7 +208,7 @@ public class ImageGalleryModule {
|
||||
}
|
||||
}
|
||||
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()) {
|
||||
DrawableDB drawableDB = controller.getDatabase();
|
||||
@ -336,21 +336,23 @@ public class ImageGalleryModule {
|
||||
try {
|
||||
ImageGalleryController con = getController();
|
||||
con.setStale(true);
|
||||
if (con.isListeningEnabled() && ImageGalleryTopComponent.isImageGalleryOpen()) {
|
||||
if (con.isListeningEnabled()) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
int showAnswer = JOptionPane.showConfirmDialog(ImageGalleryTopComponent.getTopComponent(),
|
||||
Bundle.ImageGalleryController_dataSourceAnalyzed_confDlg_msg(),
|
||||
Bundle.ImageGalleryController_dataSourceAnalyzed_confDlg_title(),
|
||||
JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
|
||||
if (ImageGalleryTopComponent.isImageGalleryOpen()) {
|
||||
int showAnswer = JOptionPane.showConfirmDialog(ImageGalleryTopComponent.getTopComponent(),
|
||||
Bundle.ImageGalleryController_dataSourceAnalyzed_confDlg_msg(),
|
||||
Bundle.ImageGalleryController_dataSourceAnalyzed_confDlg_title(),
|
||||
JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
|
||||
|
||||
switch (showAnswer) {
|
||||
case JOptionPane.YES_OPTION:
|
||||
con.rebuildDB();
|
||||
break;
|
||||
case JOptionPane.NO_OPTION:
|
||||
case JOptionPane.CANCEL_OPTION:
|
||||
default:
|
||||
break; //do nothing
|
||||
switch (showAnswer) {
|
||||
case JOptionPane.YES_OPTION:
|
||||
con.rebuildDB();
|
||||
break;
|
||||
case JOptionPane.NO_OPTION:
|
||||
case JOptionPane.CANCEL_OPTION:
|
||||
default:
|
||||
break; //do nothing
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -698,8 +698,8 @@ public final class DrawableDB {
|
||||
// query to find the group id from attribute/value
|
||||
return String.format(" SELECT group_id FROM " + GROUPS_TABLENAME
|
||||
+ " WHERE attribute = \'%s\' AND value = \'%s\' AND data_source_obj_id = %d",
|
||||
groupKey.getAttribute().attrName.toString(),
|
||||
groupKey.getValueDisplayName(),
|
||||
SleuthkitCase.escapeSingleQuotes(groupKey.getAttribute().attrName.toString()),
|
||||
SleuthkitCase.escapeSingleQuotes(groupKey.getValueDisplayName()),
|
||||
(groupKey.getAttribute() == DrawableAttribute.PATH) ? groupKey.getDataSourceObjId() : 0);
|
||||
}
|
||||
|
||||
@ -776,8 +776,8 @@ public final class DrawableDB {
|
||||
// query to find the group id from attribute/value
|
||||
String innerQuery = String.format("( SELECT group_id FROM " + GROUPS_TABLENAME
|
||||
+ " WHERE attribute = \'%s\' AND value = \'%s\' and data_source_obj_id = %d )",
|
||||
groupKey.getAttribute().attrName.toString(),
|
||||
groupKey.getValueDisplayName(),
|
||||
SleuthkitCase.escapeSingleQuotes(groupKey.getAttribute().attrName.toString()),
|
||||
SleuthkitCase.escapeSingleQuotes(groupKey.getValueDisplayName()),
|
||||
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);
|
||||
@ -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) {
|
||||
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 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()) {
|
||||
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
|
||||
boolean hasExif = 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();
|
||||
try {
|
||||
// "INSERT OR IGNORE/ INTO drawable_files (obj_id, data_source_obj_id, path, name, created_time, modified_time, make, model, analyzed)"
|
||||
@ -1006,51 +1037,55 @@ public final class DrawableDB {
|
||||
// Update the list of file IDs in memory
|
||||
addImageFileToList(f.getId());
|
||||
|
||||
// Update the hash set tables
|
||||
if (hasHashSet) {
|
||||
try {
|
||||
for (String name : f.getHashSetNames()) {
|
||||
// update the groups if we are not doing pre-populating
|
||||
if (addGroups) {
|
||||
|
||||
// "insert or ignore into hash_sets (hash_set_name) values (?)"
|
||||
insertHashSetStmt.setString(1, name);
|
||||
insertHashSetStmt.executeUpdate();
|
||||
// Update the hash set tables
|
||||
if (hasHashSet) {
|
||||
try {
|
||||
for (String name : f.getHashSetNames()) {
|
||||
|
||||
//TODO: use nested select to get hash_set_id rather than seperate statement/query
|
||||
//"select hash_set_id from hash_sets where hash_set_name = ?"
|
||||
selectHashSetStmt.setString(1, name);
|
||||
try (ResultSet rs = selectHashSetStmt.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
int hashsetID = rs.getInt("hash_set_id"); //NON-NLS
|
||||
//"insert or ignore into hash_set_hits (hash_set_id, obj_id) values (?,?)";
|
||||
insertHashHitStmt.setInt(1, hashsetID);
|
||||
insertHashHitStmt.setLong(2, f.getId());
|
||||
insertHashHitStmt.executeUpdate();
|
||||
break;
|
||||
// "insert or ignore into hash_sets (hash_set_name) values (?)"
|
||||
insertHashSetStmt.setString(1, name);
|
||||
insertHashSetStmt.executeUpdate();
|
||||
|
||||
//TODO: use nested select to get hash_set_id rather than seperate statement/query
|
||||
//"select hash_set_id from hash_sets where hash_set_name = ?"
|
||||
selectHashSetStmt.setString(1, name);
|
||||
try (ResultSet rs = selectHashSetStmt.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
int hashsetID = rs.getInt("hash_set_id"); //NON-NLS
|
||||
//"insert or ignore into hash_set_hits (hash_set_id, obj_id) values (?,?)";
|
||||
insertHashHitStmt.setInt(1, hashsetID);
|
||||
insertHashHitStmt.setLong(2, f.getId());
|
||||
insertHashHitStmt.executeUpdate();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "failed to insert/update hash hits for file" + f.getContentPathSafe(), ex); //NON-NLS
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "failed to insert/update hash hits for file" + f.getContentPathSafe(), ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
//and update all groups this file is in
|
||||
for (DrawableAttribute<?> attr : DrawableAttribute.getGroupableAttrs()) {
|
||||
// skip attributes that we do not have data for
|
||||
if ((attr == DrawableAttribute.TAGS) && (hasTag == false)) {
|
||||
continue;
|
||||
}
|
||||
else if ((attr == DrawableAttribute.MAKE || attr == DrawableAttribute.MODEL) && (hasExif == false)) {
|
||||
continue;
|
||||
}
|
||||
Collection<? extends Comparable<?>> vals = attr.getValue(f);
|
||||
for (Comparable<?> val : vals) {
|
||||
if (null != val) {
|
||||
if (attr == DrawableAttribute.PATH) {
|
||||
insertGroup(f.getAbstractFile().getDataSource().getId(), val.toString(), attr, caseDbTransaction);
|
||||
}
|
||||
else {
|
||||
insertGroup(val.toString(), attr, caseDbTransaction);
|
||||
//and update all groups this file is in
|
||||
for (DrawableAttribute<?> attr : DrawableAttribute.getGroupableAttrs()) {
|
||||
// skip attributes that we do not have data for
|
||||
if ((attr == DrawableAttribute.TAGS) && (hasTag == false)) {
|
||||
continue;
|
||||
}
|
||||
else if ((attr == DrawableAttribute.MAKE || attr == DrawableAttribute.MODEL) && (hasExif == false)) {
|
||||
continue;
|
||||
}
|
||||
Collection<? extends Comparable<?>> vals = attr.getValue(f);
|
||||
for (Comparable<?> val : vals) {
|
||||
if ((null != val) && (val.toString().isEmpty() == false)) {
|
||||
if (attr == DrawableAttribute.PATH) {
|
||||
insertGroup(f.getAbstractFile().getDataSource().getId(), val.toString(), attr, caseDbTransaction);
|
||||
}
|
||||
else {
|
||||
insertGroup(val.toString(), attr, caseDbTransaction);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1408,7 +1443,7 @@ public final class DrawableDB {
|
||||
|
||||
try {
|
||||
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()) {
|
||||
insertSQL += " ON CONFLICT DO NOTHING";
|
||||
|
@ -68,13 +68,6 @@ public class DrawableGroup implements Comparable<DrawableGroup> {
|
||||
DrawableGroup(GroupKey<?> groupKey, Set<Long> filesInGroup, boolean seen) {
|
||||
this.groupKey = groupKey;
|
||||
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);
|
||||
}
|
||||
|
||||
@ -183,15 +176,21 @@ public class DrawableGroup implements Comparable<DrawableGroup> {
|
||||
if (fileIDs.contains(f) == false) {
|
||||
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) {
|
||||
fileIDs.removeIf(fileID -> newFileIds.contains(fileID) == false);
|
||||
invalidateProperties(false);
|
||||
newFileIds.stream().forEach(this::addFile);
|
||||
}
|
||||
|
||||
synchronized void removeFile(Long f) {
|
||||
fileIDs.removeAll(f);
|
||||
if (fileIDs.contains(f)) {
|
||||
fileIDs.removeAll(f);
|
||||
invalidateProperties(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void invalidateProperties(boolean seenChanged) {
|
||||
|
@ -50,6 +50,7 @@ import javafx.beans.property.ReadOnlyBooleanWrapper;
|
||||
import javafx.beans.property.ReadOnlyDoubleProperty;
|
||||
import javafx.beans.property.ReadOnlyObjectProperty;
|
||||
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||
import javafx.beans.property.ReadOnlyStringProperty;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.concurrent.Service;
|
||||
@ -266,14 +267,23 @@ public class GroupManager {
|
||||
try {
|
||||
Examiner examiner = controller.getSleuthKitCase().getCurrentExaminer();
|
||||
getDrawableDB().markGroupSeen(group.getGroupKey(), seen, examiner.getId());
|
||||
group.setSeen(seen);
|
||||
updateUnSeenGroups(group);
|
||||
// only update and reshuffle if its new results
|
||||
if (group.isSeen() != seen) {
|
||||
group.setSeen(seen);
|
||||
updateUnSeenGroups(group);
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
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) {
|
||||
if (group.isSeen()) {
|
||||
unSeenGroups.removeAll(group);
|
||||
@ -496,6 +506,10 @@ public class GroupManager {
|
||||
return regrouper.progressProperty();
|
||||
}
|
||||
|
||||
public ReadOnlyStringProperty regroupMessage() {
|
||||
return regrouper.messageProperty();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
synchronized public void handleTagAdded(ContentTagAddedEvent evt) {
|
||||
GroupKey<?> newGroupKey = null;
|
||||
@ -530,15 +544,18 @@ public class GroupManager {
|
||||
|
||||
// NOTE: We assume that it has already been determined that GroupKey can be displayed based on Data Source filters
|
||||
if (group == null) {
|
||||
//if there wasn't already a group check if there should be one now
|
||||
// path group, for example, only gets created when all files are analyzed
|
||||
//if there wasn't already a DrawableGroup, then check if this group is now
|
||||
// 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);
|
||||
} else {
|
||||
//if there is aleady a group that was previously deemed fully analyzed, then add this newly analyzed file to it.
|
||||
group.addFile(fileID);
|
||||
}
|
||||
// reset the seen status for the group
|
||||
markGroupSeen(group, false);
|
||||
if (group != null) {
|
||||
markGroupSeen(group, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@ -607,6 +624,8 @@ public class GroupManager {
|
||||
* 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
|
||||
* that it can be viewed.
|
||||
*
|
||||
* @returns null if Group is not ready to be viewed
|
||||
*/
|
||||
synchronized private DrawableGroup popuplateIfAnalyzed(GroupKey<?> groupKey, ReGroupTask<?> task) {
|
||||
/*
|
||||
@ -716,12 +735,7 @@ public class GroupManager {
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@NbBundle.Messages({"# {0} - groupBy attribute Name",
|
||||
"# {1} - sortBy name",
|
||||
"# {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}"})
|
||||
"ReGroupTask.displayTitle=regrouping by {0}: " })
|
||||
class ReGroupTask<AttrValType extends Comparable<AttrValType>> extends LoggedTask<Void> {
|
||||
|
||||
private final DataSource dataSource;
|
||||
@ -729,16 +743,14 @@ public class GroupManager {
|
||||
private final GroupSortBy sortBy;
|
||||
private final SortOrder sortOrder;
|
||||
|
||||
private final ProgressHandle groupProgress;
|
||||
|
||||
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.groupBy = groupBy;
|
||||
this.sortBy = sortBy;
|
||||
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
|
||||
@ -747,7 +759,8 @@ public class GroupManager {
|
||||
if (isCancelled()) {
|
||||
return null;
|
||||
}
|
||||
groupProgress.start();
|
||||
|
||||
updateProgress(-1, 1);
|
||||
|
||||
analyzedGroups.clear();
|
||||
unSeenGroups.clear();
|
||||
@ -755,7 +768,7 @@ public class GroupManager {
|
||||
// Get the list of group keys
|
||||
Multimap<DataSource, AttrValType> valsByDataSource = findValuesForAttribute();
|
||||
|
||||
groupProgress.switchToDeterminate(valsByDataSource.entries().size());
|
||||
updateProgress(0, valsByDataSource.entries().size());
|
||||
int p = 0;
|
||||
// For each key value, partially create the group and add it to the list.
|
||||
for (final Map.Entry<DataSource, AttrValType> valForDataSource : valsByDataSource.entries()) {
|
||||
@ -763,9 +776,8 @@ public class GroupManager {
|
||||
return null;
|
||||
}
|
||||
p++;
|
||||
updateMessage(Bundle.ReGroupTask_progressUpdate(groupBy.attrName.toString(), valForDataSource.getValue()));
|
||||
updateMessage(Bundle.ReGroupTask_displayTitle(groupBy.attrName.toString()) + valForDataSource.getValue());
|
||||
updateProgress(p, valsByDataSource.size());
|
||||
groupProgress.progress(Bundle.ReGroupTask_progressUpdate(groupBy.attrName.toString(), valForDataSource), p);
|
||||
popuplateIfAnalyzed(new GroupKey<>(groupBy, valForDataSource.getValue(), valForDataSource.getKey()), this);
|
||||
}
|
||||
|
||||
@ -794,8 +806,8 @@ public class GroupManager {
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
groupProgress.finish();
|
||||
updateProgress(1, 1);
|
||||
updateMessage("");
|
||||
}
|
||||
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.
|
||||
*
|
||||
* @param groupBy
|
||||
*
|
||||
* @return map of data source (or null if group by attribute ignores
|
||||
* data sources) to list of unique group values
|
||||
*/
|
||||
|
@ -10,12 +10,21 @@
|
||||
<?import javafx.scene.layout.HBox?>
|
||||
<?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>
|
||||
<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>
|
||||
<HBox alignment="CENTER_RIGHT" prefHeight="-1.0" prefWidth="-1.0" spacing="5.0" BorderPane.alignment="CENTER_RIGHT">
|
||||
<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">
|
||||
<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" />
|
||||
@ -31,37 +40,27 @@
|
||||
<Insets />
|
||||
</HBox.margin>
|
||||
</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>
|
||||
<BorderPane.margin>
|
||||
<Insets left="10.0" />
|
||||
</BorderPane.margin>
|
||||
</HBox>
|
||||
</right>
|
||||
<left><Label fx:id="staleLabel" text="Some data may be out of date. Enable listening to ingest to update." BorderPane.alignment="CENTER">
|
||||
<graphic><ImageView fitHeight="16.0" fitWidth="16.0" pickOnBounds="true" preserveRatio="true">
|
||||
<image>
|
||||
<Image url="@../images/information.png" />
|
||||
</image></ImageView>
|
||||
</graphic>
|
||||
<BorderPane.margin>
|
||||
<Insets bottom="5.0" left="5.0" right="10.0" top="5.0" />
|
||||
</BorderPane.margin></Label>
|
||||
</left>
|
||||
<left>
|
||||
<StackPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="-1.0" prefWidth="-1.0" BorderPane.alignment="CENTER">
|
||||
<children>
|
||||
<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" />
|
||||
<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">
|
||||
<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>
|
||||
</StackPane>
|
||||
</left>
|
||||
</BorderPane>
|
||||
</children>
|
||||
</fx:root>
|
||||
|
@ -28,28 +28,26 @@ import javafx.scene.control.Tooltip;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
|
||||
import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupManager;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class StatusBar extends AnchorPane {
|
||||
|
||||
private final ImageGalleryController controller;
|
||||
|
||||
@FXML
|
||||
private ProgressBar fileTaskProgresBar;
|
||||
|
||||
@FXML
|
||||
private Label fileUpdateTaskLabel;
|
||||
|
||||
@FXML
|
||||
private Label bgTaskLabel;
|
||||
|
||||
private Label regroupLabel;
|
||||
@FXML
|
||||
private Label staleLabel;
|
||||
|
||||
@FXML
|
||||
private ProgressBar bgTaskProgressBar;
|
||||
private ProgressBar regroupProgressBar;
|
||||
|
||||
private final ImageGalleryController controller;
|
||||
private final GroupManager groupManager;
|
||||
|
||||
@FXML
|
||||
@NbBundle.Messages({"StatusBar.fileUpdateTaskLabel.text= File Update Tasks",
|
||||
@ -58,23 +56,25 @@ public class StatusBar extends AnchorPane {
|
||||
void initialize() {
|
||||
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 bgTaskLabel != null : "fx:id=\"bgTaskLabel\" 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 regroupLabel != null : "fx:id=\"regroupLabel\" 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()));
|
||||
fileTaskProgresBar.progressProperty().bind(controller.getDBTasksQueueSizeProperty().negate());
|
||||
|
||||
controller.regroupProgress().addListener((ov, oldSize, newSize) -> {
|
||||
groupManager.regroupProgress().addListener((ov, oldSize, newSize) -> {
|
||||
Platform.runLater(() -> {
|
||||
if (controller.regroupProgress().lessThan(1.0).get()) {
|
||||
if (groupManager.regroupProgress().lessThan(1.0).get()) {
|
||||
// Regrouping in progress
|
||||
bgTaskProgressBar.progressProperty().setValue(-1.0);
|
||||
bgTaskLabel.setText(Bundle.StatusBar_bgTaskLabel_text());
|
||||
regroupProgressBar.progressProperty().setValue(groupManager.regroupProgress().doubleValue());
|
||||
regroupLabel.setText(groupManager.regroupMessage().get());
|
||||
|
||||
} else {
|
||||
// Clear the progress bar
|
||||
bgTaskProgressBar.progressProperty().setValue(0.0);
|
||||
bgTaskLabel.setText("");
|
||||
regroupProgressBar.progressProperty().setValue(0.0);
|
||||
regroupLabel.setText("");
|
||||
}
|
||||
regroupLabel.setTooltip(new Tooltip(regroupLabel.getText()));
|
||||
});
|
||||
});
|
||||
|
||||
@ -84,6 +84,7 @@ public class StatusBar extends AnchorPane {
|
||||
|
||||
public StatusBar(ImageGalleryController controller) {
|
||||
this.controller = controller;
|
||||
this.groupManager = controller.getGroupManager();
|
||||
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("StatusBar.fxml")); //NON-NLS
|
||||
fxmlLoader.setRoot(this);
|
||||
fxmlLoader.setController(this);
|
||||
@ -93,6 +94,5 @@ public class StatusBar extends AnchorPane {
|
||||
} catch (IOException 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 --------------
|
||||
|
||||
New Features:
|
||||
|
@ -73,9 +73,7 @@
|
||||
</run-dependency>
|
||||
</dependency>
|
||||
</module-dependencies>
|
||||
<public-packages>
|
||||
<package>org.sleuthkit.autopsy.recentactivity</package>
|
||||
</public-packages>
|
||||
<public-packages/>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/gson-2.1.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/gson-2.1.jar</binary-origin>
|
||||
|
@ -37,6 +37,7 @@ import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.NetworkUtils;
|
||||
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
||||
import org.sleuthkit.autopsy.ingest.IngestJobContext;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
@ -309,7 +310,7 @@ final class Chrome extends Extract {
|
||||
} else {
|
||||
date = Long.valueOf(0);
|
||||
}
|
||||
String domain = Util.extractDomain(url);
|
||||
String domain = NetworkUtils.extractDomain(url);
|
||||
try {
|
||||
Collection<BlackboardAttribute> bbattributes = Arrays.asList(
|
||||
new BlackboardAttribute(
|
||||
@ -520,6 +521,7 @@ final class Chrome extends Extract {
|
||||
try {
|
||||
BlackboardArtifact bbart = downloadFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD);
|
||||
bbart.addAttributes(bbattributes);
|
||||
|
||||
bbartifacts.add(bbart);
|
||||
} catch (TskCoreException ex) {
|
||||
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);
|
||||
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) {
|
||||
|
||||
Collection<BlackboardAttribute> bbattributes = Arrays.asList(
|
||||
new BlackboardAttribute(
|
||||
TSK_URL, PARENT_MODULE_NAME,
|
||||
@ -618,6 +621,7 @@ final class Chrome extends Extract {
|
||||
try {
|
||||
BlackboardArtifact bbart = signonFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY);
|
||||
bbart.addAttributes(bbattributes);
|
||||
|
||||
bbartifacts.add(bbart);
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error while trying to insert Chrome login artifact.", ex); //NON-NLS
|
||||
|
@ -159,6 +159,7 @@ class ExtractIE extends Extract {
|
||||
try {
|
||||
BlackboardArtifact bbart = fav.newArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK);
|
||||
bbart.addAttributes(bbattributes);
|
||||
|
||||
bbartifacts.add(bbart);
|
||||
} catch (TskCoreException ex) {
|
||||
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.
|
||||
*
|
||||
* @param url The URL to test.
|
||||
|
@ -22,14 +22,12 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.recentactivity;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import static com.google.common.collect.Lists.newArrayList;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@ -492,7 +490,6 @@ final class FirefoxExtractor extends Extract {
|
||||
errors++;
|
||||
}
|
||||
try {
|
||||
|
||||
BlackboardArtifact bbart = downloadsFile.newArtifact(TSK_WEB_DOWNLOAD);
|
||||
bbart.addAttributes(bbattributes);
|
||||
bbartifacts.add(bbart);
|
||||
@ -642,10 +639,11 @@ final class FirefoxExtractor extends Extract {
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
* Determine if the URL should be ignored.
|
||||
*
|
||||
* @param url The URL to test.
|
||||
*
|
||||
*s
|
||||
* @return True if the URL should be ignored; otherwise false.
|
||||
*/
|
||||
private boolean isIgnoredUrl(String url) {
|
||||
|
@ -50,11 +50,11 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alex
|
||||
*
|
||||
*/
|
||||
class Util {
|
||||
|
||||
private static Logger logger = Logger.getLogger(Util.class.getName());
|
||||
private static final Logger logger = Logger.getLogger(Util.class.getName());
|
||||
|
||||
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
|
||||
*
|
||||
* @return empty string if no domain could be found
|
||||
*/
|
||||
private static String getBaseDomain(String url) {
|
||||
@ -111,7 +113,6 @@ class Util {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
String base = hostB.toString();
|
||||
// verify there are no special characters in there
|
||||
if (base.matches(".*[~`!@#$%^&\\*\\(\\)\\+={}\\[\\];:\\?<>,/ ].*")) {
|
||||
@ -123,6 +124,7 @@ class Util {
|
||||
/**
|
||||
*
|
||||
* @param value
|
||||
*
|
||||
* @return empty string if no domain name was found
|
||||
*/
|
||||
public static String extractDomain(String value) {
|
||||
@ -156,18 +158,8 @@ class Util {
|
||||
}
|
||||
|
||||
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('\\');
|
||||
filename = (lastPos < 0) ? value : value.substring(lastPos + 1);
|
||||
return filename.toString();
|
||||
return (lastPos < 0) ? value : value.substring(lastPos + 1);
|
||||
}
|
||||
|
||||
public static String getPath(String txt) {
|
||||
|
@ -1,3 +1,3 @@
|
||||
<project name="TSK_VERSION">
|
||||
<property name="TSK_VERSION" value="4.6.3"/>
|
||||
<property name="TSK_VERSION" value="4.6.4"/>
|
||||
</project>
|
||||
|
@ -38,7 +38,7 @@ PROJECT_NAME = "Autopsy User Documentation"
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# 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
|
||||
# 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
|
||||
# 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
|
||||
# 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
|
||||
app.name=${branding.token}
|
||||
### 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=RELEASE
|
||||
build.type=DEVELOPMENT
|
||||
build.type=RELEASE
|
||||
#build.type=DEVELOPMENT
|
||||
|
||||
project.org.netbeans.progress=org-netbeans-api-progress
|
||||
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