mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-14 17:06:16 +00:00
Merge branch '3788-intercase-correlation' of https://github.com/briangsweeney/autopsy into 3788-intercase-correlation
This commit is contained in:
commit
aa10c0b071
@ -647,6 +647,82 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
return artifactInstances;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves eamArtiifact instances from the database that match
|
||||
* the given list of MD5 values and optionally filters by given case.
|
||||
*
|
||||
* @param correlationCase Case id to search on, if null, searches all cases
|
||||
* @param values List of ArtifactInstance MD5 values to find matches of.
|
||||
*
|
||||
* @return List of artifact instances for a given list of MD5 values
|
||||
*/
|
||||
@Override
|
||||
public List<CorrelationAttributeCommonInstance> getArtifactInstancesByCaseValues(CorrelationCase correlationCase, List<String> values) throws EamDbException {
|
||||
CorrelationAttribute.Type aType = CorrelationAttribute.getDefaultCorrelationTypes().get(0); // Files type
|
||||
if (aType == null) {
|
||||
throw new EamDbException("Correlation Type is null");
|
||||
}
|
||||
boolean singleCase = false;
|
||||
if (correlationCase != null) {
|
||||
singleCase = false;
|
||||
}
|
||||
Connection conn = connect();
|
||||
|
||||
List<CorrelationAttributeCommonInstance> artifactInstances = new ArrayList<>();
|
||||
|
||||
CorrelationAttributeCommonInstance artifactInstance;
|
||||
PreparedStatement preparedStatement = null;
|
||||
ResultSet resultSet = null;
|
||||
|
||||
String valuesString = "";
|
||||
StringBuilder valuesFilter = new StringBuilder(values.size());
|
||||
if (!values.isEmpty()) {
|
||||
for (String value : values) {
|
||||
valuesFilter.append("'").append(value).append("',");
|
||||
}
|
||||
valuesString = valuesFilter.toString().substring(0, valuesFilter.length() - 1);
|
||||
}
|
||||
|
||||
String tableName = EamDbUtil.correlationTypeToInstanceTableName(aType);
|
||||
StringBuilder sql = new StringBuilder(9);
|
||||
sql.append("SELECT cases.case_name, cases.case_uid, data_sources.name, device_id, file_path, known_status, comment, data_sources.case_id, value FROM ");
|
||||
sql.append(tableName);
|
||||
sql.append(" LEFT JOIN cases ON ");
|
||||
sql.append(tableName);
|
||||
sql.append(".case_id=cases.id");
|
||||
sql.append(" LEFT JOIN data_sources ON ");
|
||||
sql.append(tableName);
|
||||
sql.append(".data_source_id=data_sources.id");
|
||||
sql.append(" WHERE value IN (?)");
|
||||
if (singleCase) {
|
||||
sql.append(" AND ");
|
||||
sql.append(tableName);
|
||||
sql.append(".case_id = ?");
|
||||
}
|
||||
|
||||
try {
|
||||
preparedStatement = conn.prepareStatement(sql.toString());
|
||||
preparedStatement.setString(1, valuesString);
|
||||
if (singleCase && correlationCase != null) {
|
||||
preparedStatement.setString(2, String.valueOf(correlationCase.getID()));
|
||||
}
|
||||
|
||||
resultSet = preparedStatement.executeQuery();
|
||||
while (resultSet.next()) {
|
||||
artifactInstance = getCommonEamArtifactInstanceFromResultSet(resultSet);
|
||||
artifactInstances.add(artifactInstance);
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
throw new EamDbException("Error getting artifact instances by artifactType and artifactValue.", ex); // NON-NLS
|
||||
} finally {
|
||||
EamDbUtil.closePreparedStatement(preparedStatement);
|
||||
EamDbUtil.closeResultSet(resultSet);
|
||||
EamDbUtil.closeConnection(conn);
|
||||
}
|
||||
|
||||
return artifactInstances;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves eamArtifact instances from the database that are associated
|
||||
* with the aType and filePath
|
||||
@ -1081,14 +1157,14 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an eamArtifact instance to the given knownStatus.
|
||||
* knownStatus should be BAD if the file has been tagged with a notable tag and
|
||||
* UNKNOWN otherwise. If eamArtifact
|
||||
* exists, it is updated. If eamArtifact does not exist it is added with the
|
||||
* given status.
|
||||
* Sets an eamArtifact instance to the given knownStatus. knownStatus should
|
||||
* be BAD if the file has been tagged with a notable tag and UNKNOWN
|
||||
* otherwise. If eamArtifact exists, it is updated. If eamArtifact does not
|
||||
* exist it is added with the given status.
|
||||
*
|
||||
* @param eamArtifact Artifact containing exactly one (1) ArtifactInstance.
|
||||
* @param knownStatus The status to change the artifact to. Should never be KNOWN
|
||||
* @param knownStatus The status to change the artifact to. Should never be
|
||||
* KNOWN
|
||||
*/
|
||||
@Override
|
||||
public void setArtifactInstanceKnownStatus(CorrelationAttribute eamArtifact, TskData.FileKnown knownStatus) throws EamDbException {
|
||||
@ -2356,6 +2432,32 @@ public abstract class AbstractSqlEamDb implements EamDb {
|
||||
return eamArtifactInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a ResultSet to a Common EamArtifactInstance object
|
||||
*
|
||||
* @param resultSet A resultSet with a set of values to create a
|
||||
* EamArtifactInstance object.
|
||||
*
|
||||
* @return fully populated EamArtifactInstance, or null
|
||||
*
|
||||
* @throws SQLException when an expected column name is not in the resultSet
|
||||
*/
|
||||
private CorrelationAttributeCommonInstance getCommonEamArtifactInstanceFromResultSet(ResultSet resultSet) throws SQLException, EamDbException {
|
||||
if (null == resultSet) {
|
||||
return null;
|
||||
}
|
||||
CorrelationAttributeCommonInstance eamArtifactInstance = new CorrelationAttributeCommonInstance(
|
||||
new CorrelationCase(resultSet.getInt("case_id"), resultSet.getString("case_uid"), resultSet.getString("case_name")),
|
||||
new CorrelationDataSource(-1, resultSet.getInt("case_id"), resultSet.getString("device_id"), resultSet.getString("name")),
|
||||
resultSet.getString("file_path"),
|
||||
resultSet.getString("comment"),
|
||||
TskData.FileKnown.valueOf(resultSet.getByte("known_status")),
|
||||
resultSet.getString("value")
|
||||
);
|
||||
|
||||
return eamArtifactInstance;
|
||||
}
|
||||
|
||||
private EamOrganization getEamOrganizationFromResultSet(ResultSet resultSet) throws SQLException {
|
||||
if (null == resultSet) {
|
||||
return null;
|
||||
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 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.datamodel;
|
||||
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
|
||||
|
||||
/**
|
||||
* Common Files Search usage which extends CorrelationAttributeInstance
|
||||
* by adding the MD5 value to match on for the results table.
|
||||
*/
|
||||
public class CorrelationAttributeCommonInstance extends CorrelationAttributeInstance {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* The common MD5 value
|
||||
*/
|
||||
private final String value;
|
||||
|
||||
public CorrelationAttributeCommonInstance(CorrelationCase eamCase, CorrelationDataSource eamDataSource, String filePath, String comment, TskData.FileKnown knownStatus, String value) throws EamDbException {
|
||||
super(eamCase, eamDataSource, filePath, comment, knownStatus);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
@ -223,6 +223,17 @@ public interface EamDb {
|
||||
*/
|
||||
List<CorrelationAttributeInstance> getArtifactInstancesByTypeValue(CorrelationAttribute.Type aType, String value) throws EamDbException;
|
||||
|
||||
/**
|
||||
* Retrieves eamArtiifact instances from the database that match the given
|
||||
* list of MD5 values;
|
||||
*
|
||||
* @param correlationCase Case id to search on
|
||||
* @param values List of ArtifactInstance MD5 values to find matches of.
|
||||
*
|
||||
* @return List of artifact instances for a given list of MD5 values
|
||||
*/
|
||||
List<CorrelationAttributeCommonInstance> getArtifactInstancesByCaseValues(CorrelationCase correlationCase, List<String> values) throws EamDbException;
|
||||
|
||||
/**
|
||||
* Retrieves eamArtifact instances from the database that are associated
|
||||
* with the aType and filePath
|
||||
|
@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.centralrepository.datamodel;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import org.apache.commons.dbcp2.BasicDataSource;
|
||||
|
@ -34,9 +34,9 @@ import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
|
||||
|
||||
/**
|
||||
* Sqlite implementation of the Central Repository database.
|
||||
* All methods in AbstractSqlEamDb that read or write to the database should
|
||||
* be overriden here and use appropriate locking.
|
||||
* Sqlite implementation of the Central Repository database. All methods in
|
||||
* AbstractSqlEamDb that read or write to the database should be overriden here
|
||||
* and use appropriate locking.
|
||||
*/
|
||||
public class SqliteEamDb extends AbstractSqlEamDb {
|
||||
|
||||
@ -57,7 +57,8 @@ public class SqliteEamDb extends AbstractSqlEamDb {
|
||||
*
|
||||
* @return the singleton instance of SqliteEamDb
|
||||
*
|
||||
* @throws EamDbException if one or more default correlation type(s) have an invalid db table name.
|
||||
* @throws EamDbException if one or more default correlation type(s) have an
|
||||
* invalid db table name.
|
||||
*/
|
||||
public synchronized static SqliteEamDb getInstance() throws EamDbException {
|
||||
if (instance == null) {
|
||||
@ -69,8 +70,8 @@ public class SqliteEamDb extends AbstractSqlEamDb {
|
||||
|
||||
/**
|
||||
*
|
||||
* @throws EamDbException if the AbstractSqlEamDb class has one or more default
|
||||
* correlation type(s) having an invalid db table name.
|
||||
* @throws EamDbException if the AbstractSqlEamDb class has one or more
|
||||
* default correlation type(s) having an invalid db table name.
|
||||
*/
|
||||
private SqliteEamDb() throws EamDbException {
|
||||
dbSettings = new SqliteEamDbSettings();
|
||||
@ -201,7 +202,6 @@ public class SqliteEamDb extends AbstractSqlEamDb {
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a new name/value pair in the db_info table.
|
||||
*
|
||||
@ -354,7 +354,8 @@ public class SqliteEamDb extends AbstractSqlEamDb {
|
||||
/**
|
||||
* Retrieves Data Source details based on data source device ID
|
||||
*
|
||||
* @param correlationCase the current CorrelationCase used for ensuring uniqueness of DataSource
|
||||
* @param correlationCase the current CorrelationCase used for ensuring
|
||||
* uniqueness of DataSource
|
||||
* @param dataSourceDeviceId the data source device ID number
|
||||
*
|
||||
* @return The data source
|
||||
@ -419,6 +420,25 @@ public class SqliteEamDb extends AbstractSqlEamDb {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves eamArtiifact instances from the database that match the given
|
||||
* list of MD5 values;
|
||||
*
|
||||
* @param correlationCase Case id to search on
|
||||
* @param values List of ArtifactInstance MD5 values to find matches of.
|
||||
*
|
||||
* @return List of artifact instances for a given list of MD5 values
|
||||
*/
|
||||
@Override
|
||||
public List<CorrelationAttributeCommonInstance> getArtifactInstancesByCaseValues(CorrelationCase correlationCase, List<String> values) throws EamDbException {
|
||||
try {
|
||||
acquireSharedLock();
|
||||
return super.getArtifactInstancesByCaseValues(correlationCase, values);
|
||||
} finally {
|
||||
releaseSharedLock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves eamArtifact instances from the database that are associated
|
||||
* with the aType and filePath
|
||||
@ -492,7 +512,6 @@ public class SqliteEamDb extends AbstractSqlEamDb {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Long getCountUniqueDataSources() throws EamDbException {
|
||||
try {
|
||||
@ -552,14 +571,14 @@ public class SqliteEamDb extends AbstractSqlEamDb {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an eamArtifact instance to the given knownStatus.
|
||||
* knownStatus should be BAD if the file has been tagged with a notable tag and
|
||||
* UNKNOWN otherwise. If eamArtifact
|
||||
* exists, it is updated. If eamArtifact does not exist it is added with the
|
||||
* given status.
|
||||
* Sets an eamArtifact instance to the given knownStatus. knownStatus should
|
||||
* be BAD if the file has been tagged with a notable tag and UNKNOWN
|
||||
* otherwise. If eamArtifact exists, it is updated. If eamArtifact does not
|
||||
* exist it is added with the given status.
|
||||
*
|
||||
* @param eamArtifact Artifact containing exactly one (1) ArtifactInstance.
|
||||
* @param knownStatus The status to change the artifact to. Should never be KNOWN
|
||||
* @param knownStatus The status to change the artifact to. Should never be
|
||||
* KNOWN
|
||||
*/
|
||||
@Override
|
||||
public void setArtifactInstanceKnownStatus(CorrelationAttribute eamArtifact, TskData.FileKnown knownStatus) throws EamDbException {
|
||||
@ -632,6 +651,7 @@ public class SqliteEamDb extends AbstractSqlEamDb {
|
||||
|
||||
/**
|
||||
* Remove a reference set and all values contained in it.
|
||||
*
|
||||
* @param referenceSetID
|
||||
* @throws EamDbException
|
||||
*/
|
||||
@ -647,6 +667,7 @@ public class SqliteEamDb extends AbstractSqlEamDb {
|
||||
|
||||
/**
|
||||
* Check if the given hash is in a specific reference set
|
||||
*
|
||||
* @param value
|
||||
* @param referenceSetID
|
||||
* @param correlationTypeID
|
||||
@ -663,8 +684,10 @@ public class SqliteEamDb extends AbstractSqlEamDb {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a reference set with the given name/version is in the central repo.
|
||||
* Used to check for name collisions when creating reference sets.
|
||||
* Check whether a reference set with the given name/version is in the
|
||||
* central repo. Used to check for name collisions when creating reference
|
||||
* sets.
|
||||
*
|
||||
* @param referenceSetName
|
||||
* @param version
|
||||
* @return true if a matching set is found
|
||||
@ -772,6 +795,7 @@ public class SqliteEamDb extends AbstractSqlEamDb {
|
||||
releaseExclusiveLock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new Global Set
|
||||
*
|
||||
@ -833,8 +857,7 @@ public class SqliteEamDb extends AbstractSqlEamDb {
|
||||
* Add a new reference instance
|
||||
*
|
||||
* @param eamGlobalFileInstance The reference instance to add
|
||||
* @param correlationType Correlation Type that this Reference
|
||||
* Instance is
|
||||
* @param correlationType Correlation Type that this Reference Instance is
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
@ -997,6 +1020,7 @@ public class SqliteEamDb extends AbstractSqlEamDb {
|
||||
|
||||
/**
|
||||
* Upgrade the schema of the database (if needed)
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
@Override
|
||||
@ -1010,12 +1034,14 @@ public class SqliteEamDb extends AbstractSqlEamDb {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an exclusive lock (if applicable).
|
||||
* Will return the lock if successful, null if unsuccessful because locking
|
||||
* isn't supported, and throw an exception if we should have been able to get the
|
||||
* lock but failed (meaning the database is in use).
|
||||
* Gets an exclusive lock (if applicable). Will return the lock if
|
||||
* successful, null if unsuccessful because locking isn't supported, and
|
||||
* throw an exception if we should have been able to get the lock but failed
|
||||
* (meaning the database is in use).
|
||||
*
|
||||
* @return the lock, or null if locking is not supported
|
||||
* @throws EamDbException if the coordination service is running but we fail to get the lock
|
||||
* @throws EamDbException if the coordination service is running but we fail
|
||||
* to get the lock
|
||||
*/
|
||||
@Override
|
||||
public CoordinationService.Lock getExclusiveMultiUserDbLock() throws EamDbException {
|
||||
@ -1025,35 +1051,35 @@ public class SqliteEamDb extends AbstractSqlEamDb {
|
||||
|
||||
/**
|
||||
* Acquire the lock that provides exclusive access to the case database.
|
||||
* Call this method in a try block with a call to
|
||||
* the lock release method in an associated finally block.
|
||||
* Call this method in a try block with a call to the lock release method in
|
||||
* an associated finally block.
|
||||
*/
|
||||
private void acquireExclusiveLock() {
|
||||
rwLock.writeLock().lock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Release the lock that provides exclusive access to the database.
|
||||
* This method should always be called in the finally
|
||||
* block of a try block in which the lock was acquired.
|
||||
* Release the lock that provides exclusive access to the database. This
|
||||
* method should always be called in the finally block of a try block in
|
||||
* which the lock was acquired.
|
||||
*/
|
||||
private void releaseExclusiveLock() {
|
||||
rwLock.writeLock().unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Acquire the lock that provides shared access to the case database.
|
||||
* Call this method in a try block with a call to the
|
||||
* lock release method in an associated finally block.
|
||||
* Acquire the lock that provides shared access to the case database. Call
|
||||
* this method in a try block with a call to the lock release method in an
|
||||
* associated finally block.
|
||||
*/
|
||||
private void acquireSharedLock() {
|
||||
rwLock.readLock().lock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Release the lock that provides shared access to the database.
|
||||
* This method should always be called in the finally block
|
||||
* of a try block in which the lock was acquired.
|
||||
* Release the lock that provides shared access to the database. This method
|
||||
* should always be called in the finally block of a try block in which the
|
||||
* lock was acquired.
|
||||
*/
|
||||
private void releaseSharedLock() {
|
||||
rwLock.readLock().unlock();
|
||||
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* 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.commonfilesearch;
|
||||
|
||||
import java.util.Map;
|
||||
import static org.sleuthkit.autopsy.commonfilesearch.CommonFilesMetadataBuilder.SELECT_PREFIX;
|
||||
|
||||
|
||||
/**
|
||||
* Provides logic for selecting common files from all data sources for all files to source for EamDB query.
|
||||
*/
|
||||
public class AllDataSourcesEamDbCommonFilesAlgorithm extends CommonFilesMetadataBuilder {
|
||||
|
||||
private static final String WHERE_CLAUSE = "%s md5 in (select md5 from tsk_files where (known != 1 OR known IS NULL)%s GROUP BY md5) order by md5"; //NON-NLS
|
||||
|
||||
/**
|
||||
* Implements the algorithm for getting common files across all data
|
||||
* sources.
|
||||
*
|
||||
* @param dataSourceIdMap a map of obj_id to datasource name
|
||||
* @param filterByMediaMimeType match only on files whose mime types can be broadly categorized as media types
|
||||
* @param filterByDocMimeType match only on files whose mime types can be broadly categorized as document types
|
||||
*/
|
||||
AllDataSourcesEamDbCommonFilesAlgorithm(Map<Long, String> dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType) {
|
||||
super(dataSourceIdMap, filterByMediaMimeType, filterByDocMimeType);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String buildSqlSelectStatement() {
|
||||
Object[] args = new String[]{SELECT_PREFIX, determineMimeTypeFilter()};
|
||||
return String.format(WHERE_CLAUSE, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String buildTabTitle() {
|
||||
final String buildCategorySelectionString = this.buildCategorySelectionString();
|
||||
final String titleTemplate = Bundle.CommonFilesMetadataBuilder_buildTabTitle_titleEamDb();
|
||||
return String.format(titleTemplate, new Object[]{buildCategorySelectionString});
|
||||
}
|
||||
}
|
@ -1,15 +1,21 @@
|
||||
CommonFilesPanel.searchButton.text=Search
|
||||
CommonFilesPanel.withinDataSourceRadioButton.text=At least one instance of a given MD5 must appear in the data source selected below:
|
||||
CommonFilesPanel.allDataSourcesRadioButton.text=Files can be in any data source
|
||||
CommonFilesPanel.withinDataSourceRadioButton.text=At least one match must appear in the data source selected below:
|
||||
CommonFilesPanel.allDataSourcesRadioButton.text=Matches may be from any data source
|
||||
CommonFilesPanel.cancelButton.text=Cancel
|
||||
CommonFilesPanel.cancelButton.actionCommand=Cancel
|
||||
CommonFilesPanel.selectedFileCategoriesButton.text=Match on the following file categories:
|
||||
CommonFilesPanel.selectedFileCategoriesButton.toolTipText=Select from the options below...
|
||||
CommonFilesPanel.pictureVideoCheckbox.text=Pictures and Videos
|
||||
CommonFilesPanel.documentsCheckbox.text=Documents
|
||||
CommonFilesPanel.commonFilesSearchLabel.text=<html>Find duplicate files in the current case.</html>
|
||||
CommonFilesPanel.allFileCategoriesRadioButton.toolTipText=No filtering applied to results...
|
||||
CommonFilesPanel.allFileCategoriesRadioButton.text=Match on all file types
|
||||
CommonFilesPanel.text=Indicate which data sources to consider while searching for duplicates:
|
||||
CommonFilesPanel.categoriesLabel.text=Indicate which file types to include in results:
|
||||
CommonFilesPanel.errorText.text=In order to search, you must select a file category.
|
||||
CommonFilesPanel.commonFilesSearchLabel1.text=<html>Find Common Files.</html>
|
||||
CommonFilesPanel.jRadioButton1.text=jRadioButton1
|
||||
CommonFilesPanel.jRadioButton2.text=Correlate amongst external cases (compares files in current case with Central Repo)
|
||||
CommonFilesPanel.intraCaseRadio.label=Correlate within current case only
|
||||
CommonFilesPanel.interCaseRadio.label=Correlate amongst all known cases (uses Central Repo)
|
||||
CommonFilesPanel.anCentralRepoCaseRadio.text_1=Matches may be from any Central Repo case
|
||||
CommonFilesPanel.specificCentralRepoCaseRadio.text_1=Matches must be from the following Central Repo case:
|
||||
|
@ -22,16 +22,25 @@ package org.sleuthkit.autopsy.commonfilesearch;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeCommonInstance;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||
import static org.sleuthkit.autopsy.timeline.datamodel.eventtype.ArtifactEventType.LOGGER;
|
||||
import org.sleuthkit.datamodel.HashUtility;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase.CaseDbQuery;
|
||||
@ -202,6 +211,64 @@ abstract class CommonFilesMetadataBuilder {
|
||||
return new CommonFilesMetadata(commonFiles);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO Refactor, abstract shared code above, call this method via new AllDataSourcesEamDbCommonFilesAlgorithm Class
|
||||
* @param correlationCase Optionally null, otherwise a case, or could be a CR case ID
|
||||
* @return
|
||||
* @throws TskCoreException
|
||||
* @throws NoCurrentCaseException
|
||||
* @throws SQLException
|
||||
* @throws EamDbException
|
||||
*/
|
||||
public CommonFilesMetadata findEamDbCommonFiles(CorrelationCase correlationCase) throws TskCoreException, NoCurrentCaseException, SQLException, EamDbException {
|
||||
CommonFilesMetadata metaData = this.findCommonFiles();
|
||||
Map<String, Md5Metadata> commonFiles = metaData.getMetadata();
|
||||
List<String> values = Arrays.asList((String[]) commonFiles.keySet().toArray());
|
||||
|
||||
Map<String, Md5Metadata> interCaseCommonFiles = metaData.getMetadata();
|
||||
try {
|
||||
|
||||
EamDb dbManager = EamDb.getInstance();
|
||||
Collection<CorrelationAttributeCommonInstance> artifactInstances = dbManager.getArtifactInstancesByCaseValues(correlationCase, values).stream()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
|
||||
for (CorrelationAttributeCommonInstance instance : artifactInstances) {
|
||||
//Long objectId = 1L; //TODO, need to retrieve ALL (even count < 2) AbstractFiles from this case to us for objectId for CR matches;
|
||||
String md5 = instance.getValue();
|
||||
String dataSource = instance.getCorrelationDataSource().getName();
|
||||
|
||||
if (md5 == null || HashUtility.isNoDataMd5(md5)) {
|
||||
continue;
|
||||
}
|
||||
//Builds a 3rd list which contains instances which are in commonFiles map, uses current case objectId
|
||||
if (commonFiles.containsKey(md5)) {
|
||||
// TODO sloppy, but we don't *have* all the information for the rows in the CR, so what do we do?
|
||||
Long objectId = commonFiles.get(md5).getMetadata().iterator().next().getObjectId();
|
||||
if(interCaseCommonFiles.containsKey(md5)) {
|
||||
//Add to intercase metaData
|
||||
final Md5Metadata md5Metadata = interCaseCommonFiles.get(md5);
|
||||
md5Metadata.addFileInstanceMetadata(new FileInstanceMetadata(objectId, dataSource));
|
||||
|
||||
} else {
|
||||
// Create new intercase metadata
|
||||
final Md5Metadata md5Metadata = commonFiles.get(md5);
|
||||
md5Metadata.addFileInstanceMetadata(new FileInstanceMetadata(objectId, dataSource));
|
||||
interCaseCommonFiles.put(md5, md5Metadata);
|
||||
}
|
||||
} else {
|
||||
// TODO This should never happen. All current case files with potential matches are in comonFiles Map.
|
||||
}
|
||||
}
|
||||
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error getting artifact instances from database.", ex); // NON-NLS
|
||||
}
|
||||
// Builds intercase-only matches metadata
|
||||
return new CommonFilesMetadata(interCaseCommonFiles);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be used by subclasses, in their
|
||||
* <code>buildSqlSelectStatement()</code> function to create an SQL boolean
|
||||
@ -235,7 +302,8 @@ abstract class CommonFilesMetadataBuilder {
|
||||
|
||||
@NbBundle.Messages({
|
||||
"CommonFilesMetadataBuilder.buildTabTitle.titleAll=Common Files (All Data Sources, %s)",
|
||||
"CommonFilesMetadataBuilder.buildTabTitle.titleSingle=Common Files (Match Within Data Source: %s, %s)"
|
||||
"CommonFilesMetadataBuilder.buildTabTitle.titleSingle=Common Files (Match Within Data Source: %s, %s)",
|
||||
"CommonFilesMetadataBuilder.buildTabTitle.titleEamDb=Common Files (Central Repository Source(s), %s)",
|
||||
})
|
||||
protected abstract String buildTabTitle();
|
||||
|
||||
|
@ -6,6 +6,10 @@
|
||||
</Component>
|
||||
<Component class="javax.swing.ButtonGroup" name="fileTypeFilterButtonGroup">
|
||||
</Component>
|
||||
<Component class="javax.swing.ButtonGroup" name="interIntraButtonGroup">
|
||||
</Component>
|
||||
<Component class="javax.swing.ButtonGroup" name="caseSelectionButtonGroup">
|
||||
</Component>
|
||||
</NonVisualComponents>
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||
@ -23,30 +27,17 @@
|
||||
<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" max="-2" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Component id="errorText" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="searchButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="cancelButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="categoriesLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="commonFilesSearchLabel" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="dataSourceLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="commonFilesSearchLabel1" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="categoriesLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="6" pref="6" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="29" max="-2" attributes="0"/>
|
||||
<Component id="selectDataSourceComboBox" min="-2" pref="261" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="withinDataSourceRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="allDataSourcesRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="allFileCategoriesRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="selectedFileCategoriesButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
@ -58,27 +49,75 @@
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="19" max="-2" attributes="0"/>
|
||||
<Component id="intraCaseRadio" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace min="21" pref="21" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="withinDataSourceRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="allDataSourcesRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="47" max="-2" attributes="0"/>
|
||||
<Component id="selectDataSourceComboBox" min="-2" pref="261" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="interCaseRadio" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="21" pref="21" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="anCentralRepoCaseRadio" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="specificCentralRepoCaseRadio" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="21" max="-2" attributes="0"/>
|
||||
<Component id="caseComboBox" min="-2" pref="261" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="13" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
<Component id="errorText" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="searchButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="cancelButton" min="-2" max="-2" 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 max="-2" attributes="0"/>
|
||||
<Component id="commonFilesSearchLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
|
||||
<Component id="dataSourceLabel" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="commonFilesSearchLabel1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Component id="intraCaseRadio" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="allDataSourcesRadioButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="withinDataSourceRadioButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="selectDataSourceComboBox" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="interCaseRadio" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="anCentralRepoCaseRadio" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="specificCentralRepoCaseRadio" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="caseComboBox" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="categoriesLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="selectedFileCategoriesButton" min="-2" max="-2" attributes="0"/>
|
||||
@ -94,6 +133,7 @@
|
||||
<Component id="searchButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="errorText" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -116,7 +156,6 @@
|
||||
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
|
||||
<ComponentRef name="dataSourcesButtonGroup"/>
|
||||
</Property>
|
||||
<Property name="selected" type="boolean" value="true"/>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/commonfilesearch/Bundle.properties" key="CommonFilesPanel.allDataSourcesRadioButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
@ -154,14 +193,6 @@
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<String>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="commonFilesSearchLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/commonfilesearch/Bundle.properties" key="CommonFilesPanel.commonFilesSearchLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="focusable" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="cancelButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
@ -231,14 +262,6 @@
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="documentsCheckboxActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="dataSourceLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/commonfilesearch/Bundle.properties" key="CommonFilesPanel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="name" type="java.lang.String" value="" noResource="true"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="categoriesLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
@ -257,5 +280,79 @@
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="commonFilesSearchLabel1">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/commonfilesearch/Bundle.properties" key="CommonFilesPanel.commonFilesSearchLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="focusable" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JRadioButton" name="intraCaseRadio">
|
||||
<Properties>
|
||||
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
|
||||
<ComponentRef name="interIntraButtonGroup"/>
|
||||
</Property>
|
||||
<Property name="selected" type="boolean" value="true"/>
|
||||
<Property name="label" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/commonfilesearch/Bundle.properties" key="CommonFilesPanel.intraCaseRadio.label" 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="intraCaseRadioActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JRadioButton" name="interCaseRadio">
|
||||
<Properties>
|
||||
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
|
||||
<ComponentRef name="interIntraButtonGroup"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/commonfilesearch/Bundle.properties" key="CommonFilesPanel.jRadioButton2.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="interCaseRadioActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JRadioButton" name="anCentralRepoCaseRadio">
|
||||
<Properties>
|
||||
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
|
||||
<ComponentRef name="caseSelectionButtonGroup"/>
|
||||
</Property>
|
||||
<Property name="selected" type="boolean" value="true"/>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/commonfilesearch/Bundle.properties" key="CommonFilesPanel.anCentralRepoCaseRadio.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JRadioButton" name="specificCentralRepoCaseRadio">
|
||||
<Properties>
|
||||
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
|
||||
<ComponentRef name="caseSelectionButtonGroup"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/commonfilesearch/Bundle.properties" key="CommonFilesPanel.specificCentralRepoCaseRadio.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="caseComboBox">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
|
||||
<StringArray count="4">
|
||||
<StringItem index="0" value="Item 1"/>
|
||||
<StringItem index="1" value="Item 2"/>
|
||||
<StringItem index="2" value="Item 3"/>
|
||||
<StringItem index="3" value="Item 4"/>
|
||||
</StringArray>
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<String>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -273,7 +273,10 @@ public final class CommonFilesPanel extends javax.swing.JPanel {
|
||||
builder = new SingleDataSource(dataSourceId, CommonFilesPanel.this.dataSourceMap, filterByMedia, filterByDocuments);
|
||||
|
||||
setTitleForSingleSource(dataSourceId);
|
||||
}
|
||||
}// else if(false) {
|
||||
// TODO, is CR cases, add option chosen CorrelationCase ID lookup
|
||||
// builder = new AllDataSourcesEamDbCommonFilesAlgorithm(CommonFilesPanel.this.dataSourceMap, filterByMedia, filterByDocuments);
|
||||
//}
|
||||
|
||||
this.tabTitle = builder.buildTabTitle();
|
||||
|
||||
@ -338,19 +341,25 @@ public final class CommonFilesPanel extends javax.swing.JPanel {
|
||||
|
||||
dataSourcesButtonGroup = new javax.swing.ButtonGroup();
|
||||
fileTypeFilterButtonGroup = new javax.swing.ButtonGroup();
|
||||
interIntraButtonGroup = new javax.swing.ButtonGroup();
|
||||
caseSelectionButtonGroup = new javax.swing.ButtonGroup();
|
||||
searchButton = new javax.swing.JButton();
|
||||
allDataSourcesRadioButton = new javax.swing.JRadioButton();
|
||||
withinDataSourceRadioButton = new javax.swing.JRadioButton();
|
||||
selectDataSourceComboBox = new javax.swing.JComboBox<>();
|
||||
commonFilesSearchLabel = new javax.swing.JLabel();
|
||||
cancelButton = new javax.swing.JButton();
|
||||
allFileCategoriesRadioButton = new javax.swing.JRadioButton();
|
||||
selectedFileCategoriesButton = new javax.swing.JRadioButton();
|
||||
pictureVideoCheckbox = new javax.swing.JCheckBox();
|
||||
documentsCheckbox = new javax.swing.JCheckBox();
|
||||
dataSourceLabel = new javax.swing.JLabel();
|
||||
categoriesLabel = new javax.swing.JLabel();
|
||||
errorText = new javax.swing.JLabel();
|
||||
commonFilesSearchLabel1 = new javax.swing.JLabel();
|
||||
intraCaseRadio = new javax.swing.JRadioButton();
|
||||
interCaseRadio = new javax.swing.JRadioButton();
|
||||
anCentralRepoCaseRadio = new javax.swing.JRadioButton();
|
||||
specificCentralRepoCaseRadio = new javax.swing.JRadioButton();
|
||||
caseComboBox = new javax.swing.JComboBox<>();
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(searchButton, org.openide.util.NbBundle.getMessage(CommonFilesPanel.class, "CommonFilesPanel.searchButton.text")); // NOI18N
|
||||
searchButton.setEnabled(false);
|
||||
@ -362,7 +371,6 @@ public final class CommonFilesPanel extends javax.swing.JPanel {
|
||||
});
|
||||
|
||||
dataSourcesButtonGroup.add(allDataSourcesRadioButton);
|
||||
allDataSourcesRadioButton.setSelected(true);
|
||||
org.openide.awt.Mnemonics.setLocalizedText(allDataSourcesRadioButton, org.openide.util.NbBundle.getMessage(CommonFilesPanel.class, "CommonFilesPanel.allDataSourcesRadioButton.text")); // NOI18N
|
||||
allDataSourcesRadioButton.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
|
||||
allDataSourcesRadioButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
@ -388,9 +396,6 @@ public final class CommonFilesPanel extends javax.swing.JPanel {
|
||||
}
|
||||
});
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(commonFilesSearchLabel, org.openide.util.NbBundle.getMessage(CommonFilesPanel.class, "CommonFilesPanel.commonFilesSearchLabel.text")); // NOI18N
|
||||
commonFilesSearchLabel.setFocusable(false);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(cancelButton, org.openide.util.NbBundle.getMessage(CommonFilesPanel.class, "CommonFilesPanel.cancelButton.text")); // NOI18N
|
||||
cancelButton.setActionCommand(org.openide.util.NbBundle.getMessage(CommonFilesPanel.class, "CommonFilesPanel.cancelButton.actionCommand")); // NOI18N
|
||||
cancelButton.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING);
|
||||
@ -435,42 +440,62 @@ public final class CommonFilesPanel extends javax.swing.JPanel {
|
||||
}
|
||||
});
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(dataSourceLabel, org.openide.util.NbBundle.getMessage(CommonFilesPanel.class, "CommonFilesPanel.text")); // NOI18N
|
||||
dataSourceLabel.setName(""); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(categoriesLabel, org.openide.util.NbBundle.getMessage(CommonFilesPanel.class, "CommonFilesPanel.categoriesLabel.text")); // NOI18N
|
||||
categoriesLabel.setName(""); // NOI18N
|
||||
|
||||
errorText.setForeground(new java.awt.Color(255, 0, 0));
|
||||
org.openide.awt.Mnemonics.setLocalizedText(errorText, org.openide.util.NbBundle.getMessage(CommonFilesPanel.class, "CommonFilesPanel.errorText.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(commonFilesSearchLabel1, org.openide.util.NbBundle.getMessage(CommonFilesPanel.class, "CommonFilesPanel.commonFilesSearchLabel1.text")); // NOI18N
|
||||
commonFilesSearchLabel1.setFocusable(false);
|
||||
|
||||
interIntraButtonGroup.add(intraCaseRadio);
|
||||
intraCaseRadio.setSelected(true);
|
||||
intraCaseRadio.setLabel(org.openide.util.NbBundle.getMessage(CommonFilesPanel.class, "CommonFilesPanel.intraCaseRadio.label")); // NOI18N
|
||||
intraCaseRadio.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
intraCaseRadioActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
interIntraButtonGroup.add(interCaseRadio);
|
||||
org.openide.awt.Mnemonics.setLocalizedText(interCaseRadio, org.openide.util.NbBundle.getMessage(CommonFilesPanel.class, "CommonFilesPanel.jRadioButton2.text")); // NOI18N
|
||||
interCaseRadio.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
interCaseRadioActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
caseSelectionButtonGroup.add(anCentralRepoCaseRadio);
|
||||
anCentralRepoCaseRadio.setSelected(true);
|
||||
org.openide.awt.Mnemonics.setLocalizedText(anCentralRepoCaseRadio, org.openide.util.NbBundle.getMessage(CommonFilesPanel.class, "CommonFilesPanel.anCentralRepoCaseRadio.text_1")); // NOI18N
|
||||
anCentralRepoCaseRadio.setEnabled(false);
|
||||
|
||||
caseSelectionButtonGroup.add(specificCentralRepoCaseRadio);
|
||||
org.openide.awt.Mnemonics.setLocalizedText(specificCentralRepoCaseRadio, org.openide.util.NbBundle.getMessage(CommonFilesPanel.class, "CommonFilesPanel.specificCentralRepoCaseRadio.text_1")); // NOI18N
|
||||
specificCentralRepoCaseRadio.setEnabled(false);
|
||||
|
||||
caseComboBox.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
|
||||
caseComboBox.setEnabled(false);
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addComponent(errorText)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(searchButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(cancelButton)
|
||||
.addContainerGap())
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(commonFilesSearchLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(categoriesLabel)
|
||||
.addComponent(commonFilesSearchLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(dataSourceLabel)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(6, 6, 6)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(29, 29, 29)
|
||||
.addComponent(selectDataSourceComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 261, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addComponent(withinDataSourceRadioButton)
|
||||
.addComponent(allDataSourcesRadioButton)
|
||||
.addComponent(allFileCategoriesRadioButton)
|
||||
.addComponent(selectedFileCategoriesButton)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
@ -478,22 +503,60 @@ public final class CommonFilesPanel extends javax.swing.JPanel {
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(pictureVideoCheckbox)
|
||||
.addComponent(documentsCheckbox))))))
|
||||
.addGap(19, 19, 19))))
|
||||
.addGap(277, 277, 277))
|
||||
.addComponent(intraCaseRadio)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(21, 21, 21)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(withinDataSourceRadioButton)
|
||||
.addComponent(allDataSourcesRadioButton)))))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(47, 47, 47)
|
||||
.addComponent(selectDataSourceComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 261, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(interCaseRadio)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(21, 21, 21)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(anCentralRepoCaseRadio)
|
||||
.addComponent(specificCentralRepoCaseRadio)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(21, 21, 21)
|
||||
.addComponent(caseComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 261, javax.swing.GroupLayout.PREFERRED_SIZE)))))))
|
||||
.addGap(0, 0, Short.MAX_VALUE))
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addGap(0, 0, Short.MAX_VALUE)
|
||||
.addComponent(errorText)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(searchButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(cancelButton)))
|
||||
.addContainerGap())
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(commonFilesSearchLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(commonFilesSearchLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(18, 18, 18)
|
||||
.addComponent(dataSourceLabel)
|
||||
.addComponent(intraCaseRadio)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(allDataSourcesRadioButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(withinDataSourceRadioButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(selectDataSourceComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(18, 18, 18)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(interCaseRadio)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(anCentralRepoCaseRadio)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(specificCentralRepoCaseRadio)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(caseComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(categoriesLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(selectedFileCategoriesButton)
|
||||
@ -507,7 +570,8 @@ public final class CommonFilesPanel extends javax.swing.JPanel {
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(cancelButton)
|
||||
.addComponent(searchButton)
|
||||
.addComponent(errorText)))
|
||||
.addComponent(errorText))
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
@ -555,6 +619,27 @@ public final class CommonFilesPanel extends javax.swing.JPanel {
|
||||
this.toggleErrorTextAndSearchBox();
|
||||
}//GEN-LAST:event_documentsCheckboxActionPerformed
|
||||
|
||||
private void intraCaseRadioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_intraCaseRadioActionPerformed
|
||||
this.allDataSourcesRadioButton.setEnabled(true);
|
||||
this.withinDataSourceRadioButton.setEnabled(true);
|
||||
this.selectDataSourceComboBox.setEnabled(true);
|
||||
|
||||
this.anCentralRepoCaseRadio.setEnabled(false);
|
||||
this.specificCentralRepoCaseRadio.setEnabled(false);
|
||||
this.caseComboBox.setEnabled(false);
|
||||
}//GEN-LAST:event_intraCaseRadioActionPerformed
|
||||
|
||||
private void interCaseRadioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_interCaseRadioActionPerformed
|
||||
this.anCentralRepoCaseRadio.setEnabled(true);
|
||||
this.specificCentralRepoCaseRadio.setEnabled(true);
|
||||
this.caseComboBox.setEnabled(true);
|
||||
|
||||
this.allDataSourcesRadioButton.setEnabled(false);
|
||||
this.withinDataSourceRadioButton.setEnabled(false);
|
||||
this.selectDataSourceComboBox.setEnabled(false);
|
||||
|
||||
}//GEN-LAST:event_interCaseRadioActionPerformed
|
||||
|
||||
private void toggleErrorTextAndSearchBox() {
|
||||
if (!this.pictureVideoCheckbox.isSelected() && !this.documentsCheckbox.isSelected() && !this.allFileCategoriesRadioButton.isSelected()) {
|
||||
this.searchButton.setEnabled(false);
|
||||
@ -599,18 +684,24 @@ public final class CommonFilesPanel extends javax.swing.JPanel {
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JRadioButton allDataSourcesRadioButton;
|
||||
private javax.swing.JRadioButton allFileCategoriesRadioButton;
|
||||
private javax.swing.JRadioButton anCentralRepoCaseRadio;
|
||||
private javax.swing.JButton cancelButton;
|
||||
private javax.swing.JComboBox<String> caseComboBox;
|
||||
private javax.swing.ButtonGroup caseSelectionButtonGroup;
|
||||
private javax.swing.JLabel categoriesLabel;
|
||||
private javax.swing.JLabel commonFilesSearchLabel;
|
||||
private javax.swing.JLabel dataSourceLabel;
|
||||
private javax.swing.JLabel commonFilesSearchLabel1;
|
||||
private javax.swing.ButtonGroup dataSourcesButtonGroup;
|
||||
private javax.swing.JCheckBox documentsCheckbox;
|
||||
private javax.swing.JLabel errorText;
|
||||
private javax.swing.ButtonGroup fileTypeFilterButtonGroup;
|
||||
private javax.swing.JRadioButton interCaseRadio;
|
||||
private javax.swing.ButtonGroup interIntraButtonGroup;
|
||||
private javax.swing.JRadioButton intraCaseRadio;
|
||||
private javax.swing.JCheckBox pictureVideoCheckbox;
|
||||
private javax.swing.JButton searchButton;
|
||||
private javax.swing.JComboBox<String> selectDataSourceComboBox;
|
||||
private javax.swing.JRadioButton selectedFileCategoriesButton;
|
||||
private javax.swing.JRadioButton specificCentralRepoCaseRadio;
|
||||
private javax.swing.JRadioButton withinDataSourceRadioButton;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user