diff --git a/BUILDING.txt b/BUILDING.txt index deba833a0f..6a53ff870a 100644 --- a/BUILDING.txt +++ b/BUILDING.txt @@ -56,7 +56,7 @@ the needed places (i.e. '/usr/local'). 3) For 32-bit targets, get GStreamer Setup. GStreamer is used to view video files. -You can either download it and install it or manually by unziping the +You can either download it and install it or manually by unzipping the version that is included in the 'thirdparty/gstreamer' folder. You will need the 'bin' and 'lib/gstreamer-1.0' folders to be in your Windows PATH environment variable. diff --git a/Core/build.xml b/Core/build.xml index 6ea271b16e..00bcca3a01 100644 --- a/Core/build.xml +++ b/Core/build.xml @@ -5,11 +5,7 @@ Builds, tests, and runs the project org.sleuthkit.autopsy.core - - - - - + @@ -30,7 +26,6 @@ - diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java index 718f0bb9fb..dc9774ed72 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java @@ -19,15 +19,13 @@ package org.sleuthkit.autopsy.casemodule; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.logging.Level; - import org.openide.util.NbBundle; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback; +import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback.DataSourceProcessorResult; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Image; import org.sleuthkit.datamodel.SleuthkitJNI; @@ -35,66 +33,220 @@ import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskDataException; /* - * A background task that adds the given image to database using the Sleuthkit - * JNI interface. - * - * It updates the given ProgressMonitor as it works through adding the image, - * and et the end, calls the specified Callback. + * A runnable that adds an image data source to the case database. */ class AddImageTask implements Runnable { private final Logger logger = Logger.getLogger(AddImageTask.class.getName()); - - private final Case currentCase; - - // true if the process was requested to cancel - private final Object lock = new Object(); // synchronization object for cancelRequested - private volatile boolean cancelRequested = false; - - //true if revert has been invoked. - private boolean reverted = false; - - // true if there was a critical error in adding the data source - private boolean hasCritError = false; - - private final List errorList = new ArrayList<>(); - - private final DataSourceProcessorProgressMonitor progressMonitor; - private final DataSourceProcessorCallback callbackObj; - - private final List newContents = Collections.synchronizedList(new ArrayList()); - - private SleuthkitJNI.CaseDbHandle.AddImageProcess addImageProcess; - private Thread dirFetcher; - + private final String deviceId; private final String imagePath; - String timeZone; - boolean noFatOrphans; - - private final String dataSourceId; + private final String timeZone; + private final boolean ignoreFatOrphanFiles; + private final DataSourceProcessorProgressMonitor progressMonitor; + private final DataSourceProcessorCallback callback; + private boolean criticalErrorOccurred; /* - * A thread that updates the progressMonitor with the name of the directory - * currently being processed by the AddImageTask + * The cancellation requested flag and SleuthKit add image process are + * guarded by a monitor (called a lock here to avoid confusion with the + * progress monitor) to synchronize cancelling the process (setting the flag + * and calling its stop method) and calling either its commit or revert + * method. The built-in monitor of the add image process can't be used for + * this because it is already used to synchronize its run (init part), + * commit, revert, and currentDirectory methods. + * + * TODO (AUT-2021): Merge SleuthkitJNI.AddImageProcess and AddImageTask */ - private class CurrentDirectoryFetcher implements Runnable { + private final Object tskAddImageProcessLock; + private boolean tskAddImageProcessStopped; + private SleuthkitJNI.CaseDbHandle.AddImageProcess tskAddImageProcess; - DataSourceProcessorProgressMonitor progressMonitor; - SleuthkitJNI.CaseDbHandle.AddImageProcess process; + /** + * Constructs a runnable task that adds an image to the case database. + * + * @param deviceId An ASCII-printable identifier for the device + * associated with the data source that is + * intended to be unique across multiple cases + * (e.g., a UUID). + * @param imagePath Path to the image file. + * @param timeZone The time zone to use when processing dates + * and times for the image, obtained from + * java.util.TimeZone.getID. + * @param ignoreFatOrphanFiles Whether to parse orphans if the image has a + * FAT filesystem. + * @param progressMonitor Progress monitor to report progress during + * processing. + * @param callback Callback to call when processing is done. + */ + AddImageTask(String deviceId, String imagePath, String timeZone, boolean ignoreFatOrphanFiles, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) { + this.deviceId = deviceId; + this.imagePath = imagePath; + this.timeZone = timeZone; + this.ignoreFatOrphanFiles = ignoreFatOrphanFiles; + this.callback = callback; + this.progressMonitor = progressMonitor; + tskAddImageProcessLock = new Object(); + } - CurrentDirectoryFetcher(DataSourceProcessorProgressMonitor aProgressMonitor, SleuthkitJNI.CaseDbHandle.AddImageProcess proc) { - this.progressMonitor = aProgressMonitor; - this.process = proc; + /** + * Adds the image to the case database. + */ + @Override + public void run() { + progressMonitor.setIndeterminate(true); + progressMonitor.setProgress(0); + Case currentCase = Case.getCurrentCase(); + List errorMessages = new ArrayList<>(); + List newDataSources = new ArrayList<>(); + try { + currentCase.getSleuthkitCase().acquireExclusiveLock(); + synchronized (tskAddImageProcessLock) { + tskAddImageProcess = currentCase.makeAddImageProcess(timeZone, true, ignoreFatOrphanFiles); + } + Thread progressUpdateThread = new Thread(new ProgressUpdater(progressMonitor, tskAddImageProcess)); + progressUpdateThread.start(); + runAddImageProcess(errorMessages); + if (null != progressUpdateThread) { + progressUpdateThread.interrupt(); + } + commitOrRevertAddImageProcess(currentCase, errorMessages, newDataSources); + progressMonitor.setProgress(100); + } finally { + currentCase.getSleuthkitCase().releaseExclusiveLock(); + DataSourceProcessorCallback.DataSourceProcessorResult result; + if (criticalErrorOccurred) { + result = DataSourceProcessorResult.CRITICAL_ERRORS; + } else if (!errorMessages.isEmpty()) { + result = DataSourceProcessorResult.NONCRITICAL_ERRORS; + } else { + result = DataSourceProcessorResult.NO_ERRORS; + } + callback.done(result, errorMessages, newDataSources); + } + } + + /* + * Attempts to cancel adding the image to the case database. + */ + public void cancelTask() { + synchronized (tskAddImageProcessLock) { + if (null != tskAddImageProcess) { + try { + /* + * All this does is set a flag that will make the TSK add + * image process exit when the flag is checked between + * processing steps. The state of the flag is not + * accessible, so record it here so that it is known that + * the revert method of the process object needs to be + * called. + */ + tskAddImageProcess.stop(); + tskAddImageProcessStopped = true; + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, String.format("Error cancelling adding image %s to the case database", imagePath), ex); //NON-NLS + } + } + } + } + + /** + * Runs the TSK add image process. + * + * @param errorMessages Error messages, if any, are added to this list for + * eventual return via the callback. + */ + private void runAddImageProcess(List errorMessages) { + try { + tskAddImageProcess.run(deviceId, new String[]{imagePath}); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, String.format("Critical error occurred adding image %s", imagePath), ex); //NON-NLS + criticalErrorOccurred = true; + errorMessages.add(ex.getMessage()); + } catch (TskDataException ex) { + logger.log(Level.WARNING, String.format("Non-critical error occurred adding image %s", imagePath), ex); //NON-NLS + errorMessages.add(ex.getMessage()); + } + } + + /** + * Commits or reverts the results of the TSK add image process. If the + * process was stopped before it completed or there was a critical error the + * results are reverted, otherwise they are committed. + * + * @param currentCase The current case. + * @param errorMessages Error messages, if any, are added to this list for + * eventual return via the callback. + * @param newDataSources If the new image is successfully committed, it is + * added to this list for eventual return via the + * callback. + * + * @return + */ + private void commitOrRevertAddImageProcess(Case currentCase, List errorMessages, List newDataSources) { + synchronized (tskAddImageProcessLock) { + if (tskAddImageProcessStopped || criticalErrorOccurred) { + try { + tskAddImageProcess.revert(); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, String.format("Error reverting adding image %s to the case database", imagePath), ex); //NON-NLS + errorMessages.add(ex.getMessage()); + criticalErrorOccurred = true; + } + } else { + try { + long imageId = tskAddImageProcess.commit(); + if (imageId != 0) { + Image newImage = currentCase.getSleuthkitCase().getImageById(imageId); + String verificationError = newImage.verifyImageSize(); + if (!verificationError.isEmpty()) { + errorMessages.add(verificationError); + } + newDataSources.add(newImage); + } else { + String errorMessage = String.format("Error commiting adding image %s to the case database, no object id returned", imagePath); //NON-NLS + logger.log(Level.SEVERE, errorMessage); + errorMessages.add(errorMessage); + criticalErrorOccurred = true; + } + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, String.format("Error committing adding image %s to the case database", imagePath), ex); //NON-NLS + errorMessages.add(ex.getMessage()); + criticalErrorOccurred = true; + } + } + } + } + + /** + * A Runnable that updates the progress monitor with the name of the + * directory currently being processed by the SleuthKit add image process. + */ + private class ProgressUpdater implements Runnable { + + private final DataSourceProcessorProgressMonitor progressMonitor; + private final SleuthkitJNI.CaseDbHandle.AddImageProcess tskAddImageProcess; + + /** + * Constructs a Runnable that updates the progress monitor with the name + * of the directory currently being processed by the SleuthKit. + * + * @param progressMonitor + * @param tskAddImageProcess + */ + ProgressUpdater(DataSourceProcessorProgressMonitor progressMonitor, SleuthkitJNI.CaseDbHandle.AddImageProcess tskAddImageProcess) { + this.progressMonitor = progressMonitor; + this.tskAddImageProcess = tskAddImageProcess; } /** - * @return the currently processing directory + * Updates the progress monitor with the name of the directory currently + * being processed by the SleuthKit add image process. */ @Override public void run() { try { while (!Thread.currentThread().isInterrupted()) { - String currDir = process.currentDirectory(); + String currDir = tskAddImageProcess.currentDirectory(); if (currDir != null) { if (!currDir.isEmpty()) { progressMonitor.setProgressText( @@ -102,227 +254,20 @@ class AddImageTask implements Runnable { currDir)); } } - // this sleep here prevents the UI from locking up - // due to too frequent updates to the progressMonitor above + /* + * The sleep here throttles the UI updates and provides a + * non-standard mechanism for completing this task by + * interrupting the thread in which it is running. + * + * TODO (AUT-1870): Replace this with giving the task to a + * java.util.concurrent.ScheduledThreadPoolExecutor that is + * shut down when the main task completes. + */ Thread.sleep(500); } - } catch (InterruptedException ie) { - // nothing to do, thread was interrupted externally - // signaling the end of AddImageProcess + } catch (InterruptedException expected) { } } } - /** - * Constructs a runnable task that adds an image to the case database. - * - * @param dataSourceId An ASCII-printable identifier for the data - * source that is intended to be unique across - * multiple cases (e.g., a UUID). - * @param imagePath Path to the image file. - * @param timeZone The time zone to use when processing dates - * and times for the image, obtained from - * java.util.TimeZone.getID. - * @param ignoreFatOrphanFiles Whether to parse orphans if the image has a - * FAT filesystem. - * @param monitor Progress monitor to report progress during - * processing. - * @param cbObj Callback to call when processing is done. - */ - AddImageTask(String dataSourceId, String imagePath, String timeZone, boolean ignoreFatOrphanFiles, DataSourceProcessorProgressMonitor monitor, DataSourceProcessorCallback cbObj) { - currentCase = Case.getCurrentCase(); - this.dataSourceId = dataSourceId; - this.imagePath = imagePath; - this.timeZone = timeZone; - this.noFatOrphans = ignoreFatOrphanFiles; - this.callbackObj = cbObj; - this.progressMonitor = monitor; - } - - /** - * Starts the addImage process, but does not commit the results. - * - * @return - * - * @throws Exception - */ - @Override - public void run() { - errorList.clear(); - try { - currentCase.getSleuthkitCase().acquireExclusiveLock(); - addImageProcess = currentCase.makeAddImageProcess(timeZone, true, noFatOrphans); - dirFetcher = new Thread(new CurrentDirectoryFetcher(progressMonitor, addImageProcess)); - try { - progressMonitor.setIndeterminate(true); - progressMonitor.setProgress(0); - dirFetcher.start(); - addImageProcess.run(dataSourceId, new String[]{imagePath}); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Core errors occurred while running add image on " + imagePath, ex); //NON-NLS - hasCritError = true; - errorList.add(ex.getMessage()); - } catch (TskDataException ex) { - logger.log(Level.WARNING, "Data errors occurred while running add image " + imagePath, ex); //NON-NLS - errorList.add(ex.getMessage()); - } - postProcess(); - } finally { - currentCase.getSleuthkitCase().releaseExclusiveLock(); - } - } - - /** - * Commit the newly added image to DB - * - * - * @throws Exception if commit or adding the image to the case failed - */ - private void commitImage() throws Exception { - - long imageId = 0; - try { - imageId = addImageProcess.commit(); - } catch (TskCoreException e) { - logger.log(Level.WARNING, "Errors occurred while committing the image " + imagePath, e); //NON-NLS - errorList.add(e.getMessage()); - } finally { - if (imageId != 0) { - // get the newly added Image so we can return to caller - Image newImage = currentCase.getSleuthkitCase().getImageById(imageId); - - //while we have the image, verify the size of its contents - String verificationErrors = newImage.verifyImageSize(); - if (verificationErrors.equals("") == false) { - //data error (non-critical) - errorList.add(verificationErrors); - } - - // Add the image to the list of new content - newContents.add(newImage); - } - - logger.log(Level.INFO, "Image committed, imageId: {0}", imageId); //NON-NLS - logger.log(Level.INFO, PlatformUtil.getAllMemUsageInfo()); - } - } - - /** - * Post processing after the addImageProcess is done. - * - */ - private void postProcess() { - - // cancel the directory fetcher - dirFetcher.interrupt(); - - if (cancelRequested() || hasCritError) { - logger.log(Level.WARNING, "Critical errors or interruption in add image process on {0}. Image will not be committed.", imagePath); //NON-NLS - revert(); - } - - if (!errorList.isEmpty()) { - logger.log(Level.INFO, "There were errors that occurred in add image process for {0}", imagePath); //NON-NLS - } - - // When everything happens without an error: - if (!(cancelRequested() || hasCritError)) { - try { - if (addImageProcess != null) { - // commit image - try { - commitImage(); - } catch (Exception ex) { - errorList.add(ex.getMessage()); - // Log error/display warning - logger.log(Level.SEVERE, "Error adding image " + imagePath + " to case.", ex); //NON-NLS - } - } else { - logger.log(Level.SEVERE, "Missing image process object"); //NON-NLS - } - - // Tell the progress monitor we're done - progressMonitor.setProgress(100); - } catch (Exception ex) { - //handle unchecked exceptions post image add - errorList.add(ex.getMessage()); - - logger.log(Level.WARNING, "Unexpected errors occurred while running post add image cleanup for " + imagePath, ex); //NON-NLS - logger.log(Level.SEVERE, "Error adding image " + imagePath + " to case", ex); //NON-NLS - } - } - - // invoke the callBack, unless the caller cancelled - if (!cancelRequested()) { - doCallBack(); - } - } - - /* - * Call the callback with results, new content, and errors, if any - */ - private void doCallBack() { - DataSourceProcessorCallback.DataSourceProcessorResult result; - - if (hasCritError) { - result = DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS; - } else if (!errorList.isEmpty()) { - result = DataSourceProcessorCallback.DataSourceProcessorResult.NONCRITICAL_ERRORS; - } else { - result = DataSourceProcessorCallback.DataSourceProcessorResult.NO_ERRORS; - } - - // invoke the callback, passing it the result, list of new contents, and list of errors - callbackObj.done(result, errorList, newContents); - } - - /* - * cancel the image addition, if possible - */ - public void cancelTask() { - - synchronized (lock) { - cancelRequested = true; - try { - interrupt(); - } catch (Exception ex) { - logger.log(Level.SEVERE, "Failed to interrupt the add image task..."); //NON-NLS - } - } - } - - /* - * Interrupt the add image process if it is still running - */ - private void interrupt() throws Exception { - - try { - logger.log(Level.INFO, "interrupt() add image process"); //NON-NLS - addImageProcess.stop(); //it might take time to truly stop processing and writing to db - } catch (TskCoreException ex) { - throw new Exception(NbBundle.getMessage(this.getClass(), "AddImageTask.interrupt.exception.msg"), ex); - } - } - - /* - * Revert - if image has already been added but not committed yet - */ - private void revert() { - - if (!reverted) { - logger.log(Level.INFO, "Revert after add image process"); //NON-NLS - try { - addImageProcess.revert(); - } catch (TskCoreException ex) { - logger.log(Level.WARNING, "Error reverting add image process", ex); //NON-NLS - } - reverted = true; - } - } - - private boolean cancelRequested() { - synchronized (lock) { - return cancelRequested; - } - } } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java index 1db3ab9c5c..489c713af8 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java @@ -146,6 +146,7 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { * * @param panel instance of ImageTypePanel to change to */ + @SuppressWarnings("deprecation") private void updateCurrentPanel(JPanel panel) { currentPanel = panel; typePanel.removeAll(); diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java index 46114c52fb..6e1d353e22 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java @@ -68,6 +68,7 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel errList, List contents) { dataSourceProcessorDone(dataSourceId, result, errList, contents); } - }; progressPanel.setStateStarted(); @@ -258,9 +259,6 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel { - Case.getCurrentCase().notifyFailedAddingDataSource(dataSourceId); - }).start(); dsProcessor.cancel(); } @@ -303,21 +301,23 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel { - if (!newContents.isEmpty()) { - Case.getCurrentCase().notifyDataSourceAdded(newContents.get(0), dataSourceId); + if (!contents.isEmpty()) { + Case.getCurrentCase().notifyDataSourceAdded(contents.get(0), dataSourceId); } else { Case.getCurrentCase().notifyFailedAddingDataSource(dataSourceId); } }).start(); - // Start ingest if we can - progressPanel.setStateStarted(); - startIngest(); + if (!cancelled) { + newContents.clear(); + newContents.addAll(contents); + progressPanel.setStateStarted(); + startIngest(); + } else { + cancelled = false; + } } } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 6d0aca0f6e..6615cde7e6 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -219,11 +219,11 @@ public class Case implements SleuthkitCase.ErrorObserver { * multi-user (using PostgreSql) */ @NbBundle.Messages({"Case_caseType_singleUser=Single-user case", - "Case_caseType_multiUser=Multi-user case"}) + "Case_caseType_multiUser=Multi-user case"}) public enum CaseType { - SINGLE_USER_CASE(Bundle.Case_caseType_singleUser()), - MULTI_USER_CASE(Bundle.Case_caseType_multiUser()); + SINGLE_USER_CASE("Single-user case"), //NON-NLS + MULTI_USER_CASE("Multi-user case"); //NON-NLS private final String caseType; @@ -250,6 +250,14 @@ public class Case implements SleuthkitCase.ErrorObserver { public String toString() { return caseType; } + + String getLocalizedDisplayName() { + if (fromString(caseType) == SINGLE_USER_CASE) { + return Bundle.Case_caseType_singleUser(); + } else { + return Bundle.Case_caseType_multiUser(); + } + } }; private String name; diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesForm.java b/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesForm.java index c9c4d87864..eae7cf228d 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesForm.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesForm.java @@ -92,7 +92,7 @@ class CasePropertiesForm extends javax.swing.JPanel { CaseMetadata caseMetadata = new CaseMetadata(Paths.get(currentCase.getConfigFilePath())); tbDbName.setText(caseMetadata.getCaseDatabaseName()); Case.CaseType caseType = caseMetadata.getCaseType(); - tbDbType.setText(caseType.toString()); + tbDbType.setText(caseType.getLocalizedDisplayName()); if (caseType == Case.CaseType.SINGLE_USER_CASE) { deleteCaseButton.setEnabled(true); } else { diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CollaborationMonitor.java b/Core/src/org/sleuthkit/autopsy/casemodule/CollaborationMonitor.java index 0fb3601d88..afa68ac5c3 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CollaborationMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CollaborationMonitor.java @@ -466,7 +466,11 @@ final class CollaborationMonitor { */ @Override public void run() { - eventPublisher.publishRemotely(new CollaborationEvent(hostName, localTasksManager.getCurrentTasks())); + try { + eventPublisher.publishRemotely(new CollaborationEvent(hostName, localTasksManager.getCurrentTasks())); + } catch (Exception ex) { + logger.log(Level.SEVERE, "Unexpected exception in HeartbeatTask", ex); //NON-NLS + } } } @@ -482,7 +486,11 @@ final class CollaborationMonitor { */ @Override public void run() { - remoteTasksManager.finishStaleTasks(); + try { + remoteTasksManager.finishStaleTasks(); + } catch (Exception ex) { + logger.log(Level.SEVERE, "Unexpected exception in StaleTaskDetectionTask", ex); //NON-NLS + } } } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java index be3c9466a7..fa9f92188c 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java @@ -31,7 +31,7 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; /** - * An image file data source processor that implements the DataSourceProcessor + * A image file data source processor that implements the DataSourceProcessor * service provider interface to allow integration with the add data source * wizard. It also provides a run method overload to allow it to be used * independently of the wizard. @@ -81,10 +81,10 @@ public class ImageDSProcessor implements DataSourceProcessor { /** * Gets a string that describes the type of data sources this processor is - * able to process. + * able to add to the case database. The string is suitable for display in a + * type selection UI component (e.g., a combo box). * - * @return A string suitable for display in a data source processor - * selection UI component (e.g., a combo box). + * @return A data source type display string for this data source processor. */ public static String getType() { return DATA_SOURCE_TYPE; @@ -92,21 +92,23 @@ public class ImageDSProcessor implements DataSourceProcessor { /** * Gets a string that describes the type of data sources this processor is - * able to process. + * able to add to the case database. The string is suitable for display in a + * type selection UI component (e.g., a combo box). * - * @return A string suitable for display in a data source processor - * selection UI component (e.g., a combo box). + * @return A data source type display string for this data source processor. */ @Override public String getDataSourceType() { - return DATA_SOURCE_TYPE; + return getType(); } /** * Gets the panel that allows a user to select a data source and do any - * configuration the data source processor may require. + * configuration required by the data source. The panel is less than 544 + * pixels wide and less than 173 pixels high. * - * @return A JPanel less than 544 pixels wide and 173 pixels high. + * @return A selection and configuration panel for this data source + * processor. */ @Override public JPanel getPanel() { @@ -116,10 +118,11 @@ public class ImageDSProcessor implements DataSourceProcessor { } /** - * Indicates whether the settings in the panel are valid and complete. + * Indicates whether the settings in the selection and configuration panel + * are valid and complete. * * @return True if the settings are valid and complete and the processor is - * ready to have its run method called; false otherwise. + * ready to have its run method called, false otherwise. */ @Override public boolean isPanelValid() { @@ -127,16 +130,18 @@ public class ImageDSProcessor implements DataSourceProcessor { } /** - * Adds a data source to the case database using a separate thread and the - * settings provided by the panel. Returns as soon as the background task is - * started and uses the callback object to signal task completion and return - * results. + * Adds a data source to the case database using a background task in a + * separate thread and the settings provided by the selection and + * configuration panel. Returns as soon as the background task is started. + * The background task uses a callback object to signal task completion and + * return results. * - * NOTE: This method should not be called unless isPanelValid returns true. + * This method should not be called unless isPanelValid returns true. * - * @param progressMonitor Progress monitor for reporting progress during - * processing. - * @param callback Callback to call when processing is done. + * @param progressMonitor Progress monitor that will be used by the + * background task to report progress. + * @param callback Callback that will be used by the background task + * to return results. */ @Override public void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) { @@ -151,10 +156,11 @@ public class ImageDSProcessor implements DataSourceProcessor { } /** - * Adds a data source to the case database using a separate thread and the - * given settings instead of those provided by the panel. Returns as soon as - * the background task is started and uses the callback object to signal - * task completion and return results. + * Adds a data source to the case database using a background task in a + * separate thread and the given settings instead of those provided by the + * selection and configuration panel. Returns as soon as the background task + * is started and uses the callback object to signal task completion and + * return results. * * @param deviceId An ASCII-printable identifier for the device * associated with the data source that is @@ -176,8 +182,11 @@ public class ImageDSProcessor implements DataSourceProcessor { } /** - * Requests cancellation of the data source processing task after it is - * started using the run method. Cancellation is not guaranteed. + * Requests cancellation of the background task that adds a data source to + * the case database, after the task is started using the run method. This + * is a "best effort" cancellation, with no guarantees that the case + * database will be unchanged. If cancellation succeeded, the list of new + * data sources returned by the background task will be empty. */ @Override public void cancel() { @@ -185,7 +194,8 @@ public class ImageDSProcessor implements DataSourceProcessor { } /** - * Resets the panel. + * Resets the selection and configuration panel for this data source + * processor. */ @Override public void reset() { @@ -199,7 +209,7 @@ public class ImageDSProcessor implements DataSourceProcessor { /** * Sets the configuration of the data source processor without using the - * configuration panel. + * selection and configuration panel. * * @param imagePath Path to the image file. * @param timeZone The time zone to use when processing dates diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java index 4d59cd4d91..5c7cca0a59 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java @@ -190,7 +190,7 @@ public class ImageFilePanel extends JPanel implements DocumentListener { .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); }// //GEN-END:initComponents - + @SuppressWarnings("deprecation") private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed String oldText = pathTextField.getText(); // set the current directory of the FileChooser if the ImagePath Field is valid diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java index cb80535e01..c699eb740d 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java @@ -61,10 +61,10 @@ public class LocalDiskDSProcessor implements DataSourceProcessor { /** * Gets a string that describes the type of data sources this processor is - * able to process. + * able to add to the case database. The string is suitable for display in a + * type selection UI component (e.g., a combo box). * - * @return A string suitable for display in a data source processor - * selection UI component (e.g., a combo box). + * @return A data source type display string for this data source processor. */ public static String getType() { return DATA_SOURCE_TYPE; @@ -72,10 +72,10 @@ public class LocalDiskDSProcessor implements DataSourceProcessor { /** * Gets a string that describes the type of data sources this processor is - * able to process. + * able to add to the case database. The string is suitable for display in a + * type selection UI component (e.g., a combo box). * - * @return A string suitable for display in a data source processor - * selection UI component (e.g., a combo box). + * @return A data source type display string for this data source processor. */ @Override public String getDataSourceType() { @@ -83,10 +83,12 @@ public class LocalDiskDSProcessor implements DataSourceProcessor { } /** - * Gets the JPanel that allows a user to select a data source and do any - * configuration the data source processor may require. + * Gets the panel that allows a user to select a data source and do any + * configuration required by the data source. The panel is less than 544 + * pixels wide and less than 173 pixels high. * - * @return A JPanel less than 544 pixels wide and 173 pixels high. + * @return A selection and configuration panel for this data source + * processor. */ @Override public JPanel getPanel() { @@ -95,10 +97,11 @@ public class LocalDiskDSProcessor implements DataSourceProcessor { } /** - * Indicates whether the settings in the panel are valid and complete. + * Indicates whether the settings in the selection and configuration panel + * are valid and complete. * * @return True if the settings are valid and complete and the processor is - * ready to have its run method called; false otherwise. + * ready to have its run method called, false otherwise. */ @Override public boolean isPanelValid() { @@ -106,16 +109,18 @@ public class LocalDiskDSProcessor implements DataSourceProcessor { } /** - * Adds a data source to the case database using a separate thread and the - * settings provided by the panel. Returns as soon as the background task is - * started and uses the callback object to signal task completion and return - * results. + * Adds a data source to the case database using a background task in a + * separate thread and the settings provided by the selection and + * configuration panel. Returns as soon as the background task is started. + * The background task uses a callback object to signal task completion and + * return results. * - * NOTE: This method should not be called unless isPanelValid returns true. + * This method should not be called unless isPanelValid returns true. * - * @param progressMonitor Progress monitor for reporting progress during - * processing. - * @param callback Callback to call when processing is done. + * @param progressMonitor Progress monitor that will be used by the + * background task to report progress. + * @param callback Callback that will be used by the background task + * to return results. */ @Override public void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) { @@ -130,10 +135,11 @@ public class LocalDiskDSProcessor implements DataSourceProcessor { } /** - * Adds a data source to the case database using a separate thread and the - * given settings instead of those provided by the panel. Returns as soon as - * the background task is started and uses the callback object to signal - * task completion and return results. + * Adds a data source to the case database using a background task in a + * separate thread and the given settings instead of those provided by the + * selection and configuration panel. Returns as soon as the background task + * is started and uses the callback object to signal task completion and + * return results. * * @param deviceId An ASCII-printable identifier for the device * associated with the data source that is @@ -155,8 +161,11 @@ public class LocalDiskDSProcessor implements DataSourceProcessor { } /** - * Requests cancellation of the data source processing task after it is - * started using the run method. Cancellation is not guaranteed. + * Requests cancellation of the background task that adds a data source to + * the case database, after the task is started using the run method. This + * is a "best effort" cancellation, with no guarantees that the case + * database will be unchanged. If cancellation succeeded, the list of new + * data sources returned by the background task will be empty. */ @Override public void cancel() { @@ -164,7 +173,8 @@ public class LocalDiskDSProcessor implements DataSourceProcessor { } /** - * Resets the panel. + * Resets the selection and configuration panel for this data source + * processor. */ @Override public void reset() { diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java index 6d5c028cbb..4eae9e4e7e 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java @@ -59,10 +59,10 @@ public class LocalFilesDSProcessor implements DataSourceProcessor { /** * Gets a string that describes the type of data sources this processor is - * able to process. + * able to add to the case database. The string is suitable for display in a + * type selection UI component (e.g., a combo box). * - * @return A string suitable for display in a data source processor - * selection UI component (e.g., a combo box). + * @return A data source type display string for this data source processor. */ public static String getType() { return DATA_SOURCE_TYPE; @@ -70,10 +70,10 @@ public class LocalFilesDSProcessor implements DataSourceProcessor { /** * Gets a string that describes the type of data sources this processor is - * able to process. + * able to add to the case database. The string is suitable for display in a + * type selection UI component (e.g., a combo box). * - * @return A string suitable for display in a data source processor - * selection UI component (e.g., a combo box). + * @return A data source type display string for this data source processor. */ @Override public String getDataSourceType() { @@ -82,9 +82,11 @@ public class LocalFilesDSProcessor implements DataSourceProcessor { /** * Gets the panel that allows a user to select a data source and do any - * configuration the data source processor may require. + * configuration required by the data source. The panel is less than 544 + * pixels wide and less than 173 pixels high. * - * @return A JPanel less than 544 pixels wide and 173 pixels high. + * @return A selection and configuration panel for this data source + * processor. */ @Override public JPanel getPanel() { @@ -93,10 +95,11 @@ public class LocalFilesDSProcessor implements DataSourceProcessor { } /** - * Indicates whether the settings in the panel are valid and complete. + * Indicates whether the settings in the selection and configuration panel + * are valid and complete. * * @return True if the settings are valid and complete and the processor is - * ready to have its run method called; false otherwise. + * ready to have its run method called, false otherwise. */ @Override public boolean isPanelValid() { @@ -104,16 +107,18 @@ public class LocalFilesDSProcessor implements DataSourceProcessor { } /** - * Adds a data source to the case database using a separate thread and the - * settings provided by the panel. Returns as soon as the background task is - * started and uses the callback object to signal task completion and return - * results. + * Adds a data source to the case database using a background task in a + * separate thread and the settings provided by the selection and + * configuration panel. Returns as soon as the background task is started. + * The background task uses a callback object to signal task completion and + * return results. * - * NOTE: This method should not be called unless isPanelValid returns true. + * This method should not be called unless isPanelValid returns true. * - * @param progressMonitor Progress monitor for reporting progress during - * processing. - * @param callback Callback to call when processing is done. + * @param progressMonitor Progress monitor that will be used by the + * background task to report progress. + * @param callback Callback that will be used by the background task + * to return results. */ @Override public void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) { @@ -125,10 +130,11 @@ public class LocalFilesDSProcessor implements DataSourceProcessor { } /** - * Adds a data source to the case database using a separate thread and the - * given settings instead of those provided by the panel. Returns as soon as - * the background task is started and uses the callback object to signal - * task completion and return results. + * Adds a data source to the case database using a background task in a + * separate thread and the given settings instead of those provided by the + * selection and configuration panel. Returns as soon as the background task + * is started and uses the callback object to signal task completion and + * return results. * * @param deviceId An ASCII-printable identifier for the * device associated with the data source @@ -151,18 +157,22 @@ public class LocalFilesDSProcessor implements DataSourceProcessor { } /** - * Requests cancellation of the data source processing task after it is - * started using the run method. Cancellation is not guaranteed. + * Requests cancellation of the background task that adds a data source to + * the case database, after the task is started using the run method. This + * is a "best effort" cancellation, with no guarantees that the case + * database will be unchanged. If cancellation succeeded, the list of new + * data sources returned by the background task will be empty. + * + * TODO (AUT-1907): Implement cancellation by deleting rows added to the + * case database. */ @Override public void cancel() { - /* - * Cancellation is not currently supported. - */ } /** - * Resets the panel. + * Resets the selection and configuration panel for this data source + * processor. */ @Override public void reset() { diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardPanel1.java b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardPanel1.java index b7b432a9eb..24c1e2a17e 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardPanel1.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardPanel1.java @@ -239,7 +239,7 @@ class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -37,86 +37,66 @@ import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; /** - * A per case instance of this class functions as an Autopsy service that - * manages the creation, updating, and deletion of tags applied to content and - * blackboard artifacts by users. + * A per case Autopsy service that manages the creation, updating, and deletion + * of tags applied to content and blackboard artifacts by users. */ public class TagsManager implements Closeable { + private static final Logger logger = Logger.getLogger(TagsManager.class.getName()); private static final String TAGS_SETTINGS_NAME = "Tags"; //NON-NLS private static final String TAG_NAMES_SETTING_KEY = "TagNames"; //NON-NLS - private final SleuthkitCase tskCase; + private final SleuthkitCase caseDb; private final HashMap uniqueTagNames = new HashMap<>(); - private boolean tagNamesInitialized = false; // @@@ This is part of a work around to be removed when database access on the EDT is correctly synchronized. + private boolean tagNamesLoaded = false; /** - * Use this exception and the member hash map to manage uniqueness of hash - * names. This is deemed more proactive and informative than leaving this to - * the UNIQUE constraint on the display_name field of the tag_names table in - * the case database. - */ - public static class TagNameAlreadyExistsException extends Exception { - } - - /** - * Package-scope constructor for use of the Services class. An instance of - * TagsManager should be created for each case that is opened. + * Constructs a per case Autopsy service that manages the creation, + * updating, and deletion of tags applied to content and blackboard + * artifacts by users. * - * @param tskCase The SleuthkitCase object for the current case. + * @param caseDb The case database for the current case. */ - TagsManager(SleuthkitCase tskCase) { - this.tskCase = tskCase; - // @@@ The removal of this call is a work around until database access on the EDT is correctly synchronized. - // getExistingTagNames(); + TagsManager(SleuthkitCase caseDb) { + this.caseDb = caseDb; } /** * Gets a list of all tag names currently available for tagging content or - * blackboard artifacts. + * artifacts. * * @return A list, possibly empty, of TagName data transfer objects (DTOs). * - * @throws TskCoreException + * @throws TskCoreException If there is an error reading from the case + * database. */ public synchronized List getAllTagNames() throws TskCoreException { - // @@@ This is a work around to be removed when database access on the EDT is correctly synchronized. - if (!tagNamesInitialized) { - getExistingTagNames(); - } - - return tskCase.getAllTagNames(); + lazyLoadExistingTagNames(); + return caseDb.getAllTagNames(); } /** - * Gets a list of all tag names currently used for tagging content or - * blackboard artifacts. + * Gets a list of all tag names currently in use for tagging content or + * artifacts. * * @return A list, possibly empty, of TagName data transfer objects (DTOs). * - * @throws TskCoreException + * @throws TskCoreException If there is an error reading from the case + * database. */ public synchronized List getTagNamesInUse() throws TskCoreException { - // @@@ This is a work around to be removed when database access on the EDT is correctly synchronized. - if (!tagNamesInitialized) { - getExistingTagNames(); - } - - return tskCase.getTagNamesInUse(); + lazyLoadExistingTagNames(); + return caseDb.getTagNamesInUse(); } /** * Checks whether a tag name with a given display name exists. * - * @param tagDisplayName The display name for which to check. + * @param tagDisplayName The display name to check. * - * @return True if the tag name exists, false otherwise. + * @return True or false. */ public synchronized boolean tagNameExists(String tagDisplayName) { - // @@@ This is a work around to be removed when database access on the EDT is correctly synchronized. - if (!tagNamesInitialized) { - getExistingTagNames(); - } - + lazyLoadExistingTagNames(); return uniqueTagNames.containsKey(tagDisplayName); } @@ -128,7 +108,10 @@ public class TagsManager implements Closeable { * @return A TagName data transfer object (DTO) representing the new tag * name. * - * @throws TagNameAlreadyExistsException, TskCoreException + * @throws TagNameAlreadyExistsException If the tag name would be a + * duplicate. + * @throws TskCoreException If there is an error adding the tag + * to the case database. */ public TagName addTagName(String displayName) throws TagNameAlreadyExistsException, TskCoreException { return addTagName(displayName, "", TagName.HTML_COLOR.NONE); @@ -143,7 +126,10 @@ public class TagsManager implements Closeable { * @return A TagName data transfer object (DTO) representing the new tag * name. * - * @throws TagNameAlreadyExistsException, TskCoreException + * @throws TagNameAlreadyExistsException If the tag name would be a + * duplicate. + * @throws TskCoreException If there is an error adding the tag + * to the case database. */ public TagName addTagName(String displayName, String description) throws TagNameAlreadyExistsException, TskCoreException { return addTagName(displayName, description, TagName.HTML_COLOR.NONE); @@ -159,22 +145,25 @@ public class TagsManager implements Closeable { * @return A TagName data transfer object (DTO) representing the new tag * name. * - * @throws TagNameAlreadyExistsException, TskCoreException + * @throws TagNameAlreadyExistsException If the tag name would be a + * duplicate. + * @throws TskCoreException If there is an error adding the tag + * to the case database. */ public synchronized TagName addTagName(String displayName, String description, TagName.HTML_COLOR color) throws TagNameAlreadyExistsException, TskCoreException { - // @@@ This is a work around to be removed when database access on the EDT is correctly synchronized. - if (!tagNamesInitialized) { - getExistingTagNames(); - } - + lazyLoadExistingTagNames(); if (uniqueTagNames.containsKey(displayName)) { throw new TagNameAlreadyExistsException(); } - // Add the tag name to the case. - TagName newTagName = tskCase.addTagName(displayName, description, color); + /* + * Add the tag name to the case. + */ + TagName newTagName = caseDb.addTagName(displayName, description, color); - // Add the tag name to the tags settings. + /* + * Add the tag name to the tags settings. + */ uniqueTagNames.put(newTagName.getDisplayName(), newTagName); saveTagNamesToTagsSettings(); @@ -189,7 +178,8 @@ public class TagsManager implements Closeable { * * @return A ContentTag data transfer object (DTO) representing the new tag. * - * @throws TskCoreException + * @throws TskCoreException If there is an error adding the tag to the case + * database. */ public ContentTag addContentTag(Content content, TagName tagName) throws TskCoreException { return addContentTag(content, tagName, "", -1, -1); @@ -204,7 +194,8 @@ public class TagsManager implements Closeable { * * @return A ContentTag data transfer object (DTO) representing the new tag. * - * @throws TskCoreException + * @throws TskCoreException If there is an error adding the tag to the case + * database. */ public ContentTag addContentTag(Content content, TagName tagName, String comment) throws TskCoreException { return addContentTag(content, tagName, comment, -1, -1); @@ -221,39 +212,44 @@ public class TagsManager implements Closeable { * * @return A ContentTag data transfer object (DTO) representing the new tag. * - * @throws IllegalArgumentException, TskCoreException + * @throws IllegalArgumentException If a requested byte offset is out of + * range. + * @throws TskCoreException If there is an error adding the tag to + * the case database. */ - public synchronized ContentTag addContentTag(Content content, TagName tagName, String comment, long beginByteOffset, long endByteOffset) throws IllegalArgumentException, TskCoreException { - // @@@ This is a work around to be removed when database access on the EDT is correctly synchronized. - if (!tagNamesInitialized) { - getExistingTagNames(); + public ContentTag addContentTag(Content content, TagName tagName, String comment, long beginByteOffset, long endByteOffset) throws IllegalArgumentException, TskCoreException { + ContentTag tag; + synchronized (this) { + lazyLoadExistingTagNames(); + + if (beginByteOffset >= 0 && endByteOffset >= 1) { + if (beginByteOffset > content.getSize() - 1) { + throw new IllegalArgumentException(NbBundle.getMessage(this.getClass(), + "TagsManager.addContentTag.exception.beginByteOffsetOOR.msg", + beginByteOffset, content.getSize() - 1)); + } + + if (endByteOffset > content.getSize() - 1) { + throw new IllegalArgumentException( + NbBundle.getMessage(this.getClass(), "TagsManager.addContentTag.exception.endByteOffsetOOR.msg", + endByteOffset, content.getSize() - 1)); + } + + if (endByteOffset < beginByteOffset) { + throw new IllegalArgumentException( + NbBundle.getMessage(this.getClass(), "TagsManager.addContentTag.exception.endLTbegin.msg")); + } + } + + tag = caseDb.addContentTag(content, tagName, comment, beginByteOffset, endByteOffset); } - if (beginByteOffset >= 0 && endByteOffset >= 1) { - if (beginByteOffset > content.getSize() - 1) { - throw new IllegalArgumentException(NbBundle.getMessage(this.getClass(), - "TagsManager.addContentTag.exception.beginByteOffsetOOR.msg", - beginByteOffset, content.getSize() - 1)); - } - - if (endByteOffset > content.getSize() - 1) { - throw new IllegalArgumentException( - NbBundle.getMessage(this.getClass(), "TagsManager.addContentTag.exception.endByteOffsetOOR.msg", - endByteOffset, content.getSize() - 1)); - } - - if (endByteOffset < beginByteOffset) { - throw new IllegalArgumentException( - NbBundle.getMessage(this.getClass(), "TagsManager.addContentTag.exception.endLTbegin.msg")); - } - } - final ContentTag newContentTag = tskCase.addContentTag(content, tagName, comment, beginByteOffset, endByteOffset); try { - Case.getCurrentCase().notifyContentTagAdded(newContentTag); + Case.getCurrentCase().notifyContentTagAdded(tag); } catch (IllegalStateException ex) { - Logger.getLogger(TagsManager.class.getName()).log(Level.WARNING, NbBundle.getMessage(TagsManager.class, "TagsManager.addContentTag.noCaseWarning")); + logger.log(Level.SEVERE, NbBundle.getMessage(TagsManager.class, "TagsManager.addContentTag.noCaseWarning"), ex); } - return newContentTag; + return tag; } /** @@ -261,19 +257,19 @@ public class TagsManager implements Closeable { * * @param tag The tag to delete. * - * @throws TskCoreException + * @throws TskCoreException If there is an error deleting the tag from the + * case database. */ - public synchronized void deleteContentTag(ContentTag tag) throws TskCoreException { - // @@@ This is a work around to be removed when database access on the EDT is correctly synchronized. - if (!tagNamesInitialized) { - getExistingTagNames(); + public void deleteContentTag(ContentTag tag) throws TskCoreException { + synchronized (this) { + lazyLoadExistingTagNames(); + caseDb.deleteContentTag(tag); } - tskCase.deleteContentTag(tag); try { Case.getCurrentCase().notifyContentTagDeleted(tag); - } catch (IllegalStateException e) { - Logger.getLogger(TagsManager.class.getName()).log(Level.WARNING, NbBundle.getMessage(TagsManager.class, "TagsManager.deleteContentTag.noCaseWarning")); + } catch (IllegalStateException ex) { + logger.log(Level.SEVERE, NbBundle.getMessage(TagsManager.class, "TagsManager.deleteContentTag.noCaseWarning"), ex); } } @@ -282,15 +278,12 @@ public class TagsManager implements Closeable { * * @return A list, possibly empty, of content tags. * - * @throws TskCoreException + * @throws TskCoreException If there is an error getting the tags from the + * case database. */ - public List getAllContentTags() throws TskCoreException { - // @@@ This is a work around to be removed when database access on the EDT is correctly synchronized. - if (!tagNamesInitialized) { - getExistingTagNames(); - } - - return tskCase.getAllContentTags(); + public synchronized List getAllContentTags() throws TskCoreException { + lazyLoadExistingTagNames(); + return caseDb.getAllContentTags(); } /** @@ -300,15 +293,12 @@ public class TagsManager implements Closeable { * * @return A count of the content tags with the specified tag name. * - * @throws TskCoreException + * @throws TskCoreException If there is an error getting the tags count from + * the case database. */ public synchronized long getContentTagsCountByTagName(TagName tagName) throws TskCoreException { - // @@@ This is a work around to be removed when database access on the EDT is correctly synchronized. - if (!tagNamesInitialized) { - getExistingTagNames(); - } - - return tskCase.getContentTagsCountByTagName(tagName); + lazyLoadExistingTagNames(); + return caseDb.getContentTagsCountByTagName(tagName); } /** @@ -316,17 +306,14 @@ public class TagsManager implements Closeable { * * @param tagID The tag id of interest. * - * @return the content tag with the specified tag id. + * @return The content tag with the specified tag id. * - * @throws TskCoreException + * @throws TskCoreException If there is an error getting the tag from the + * case database. */ public synchronized ContentTag getContentTagByTagID(long tagID) throws TskCoreException { - // @@@ This is a work around to be removed when database access on the EDT is correctly synchronized. - if (!tagNamesInitialized) { - getExistingTagNames(); - } - - return tskCase.getContentTagByID(tagID); + lazyLoadExistingTagNames(); + return caseDb.getContentTagByID(tagID); } /** @@ -337,15 +324,12 @@ public class TagsManager implements Closeable { * @return A list, possibly empty, of the content tags with the specified * tag name. * - * @throws TskCoreException + * @throws TskCoreException If there is an error getting the tags from the + * case database. */ public synchronized List getContentTagsByTagName(TagName tagName) throws TskCoreException { - // @@@ This is a work around to be removed when database access on the EDT is correctly synchronized. - if (!tagNamesInitialized) { - getExistingTagNames(); - } - - return tskCase.getContentTagsByTagName(tagName); + lazyLoadExistingTagNames(); + return caseDb.getContentTagsByTagName(tagName); } /** @@ -356,15 +340,12 @@ public class TagsManager implements Closeable { * @return A list, possibly empty, of the tags that have been applied to the * artifact. * - * @throws TskCoreException + * @throws TskCoreException If there is an error getting the tags from the + * case database. */ public synchronized List getContentTagsByContent(Content content) throws TskCoreException { - // @@@ This is a work around to be removed when database access on the EDT is correctly synchronized. - if (!tagNamesInitialized) { - getExistingTagNames(); - } - - return tskCase.getContentTagsByContent(content); + lazyLoadExistingTagNames(); + return caseDb.getContentTagsByContent(content); } /** @@ -376,7 +357,8 @@ public class TagsManager implements Closeable { * @return A BlackboardArtifactTag data transfer object (DTO) representing * the new tag. * - * @throws TskCoreException + * @throws TskCoreException If there is an error adding the tag to the case + * database. */ public BlackboardArtifactTag addBlackboardArtifactTag(BlackboardArtifact artifact, TagName tagName) throws TskCoreException { return addBlackboardArtifactTag(artifact, tagName, ""); @@ -392,21 +374,22 @@ public class TagsManager implements Closeable { * @return A BlackboardArtifactTag data transfer object (DTO) representing * the new tag. * - * @throws TskCoreException + * @throws TskCoreException If there is an error adding the tag to the case + * database. */ - public synchronized BlackboardArtifactTag addBlackboardArtifactTag(BlackboardArtifact artifact, TagName tagName, String comment) throws TskCoreException { - // @@@ This is a work around to be removed when database access on the EDT is correctly synchronized. - if (!tagNamesInitialized) { - getExistingTagNames(); + public BlackboardArtifactTag addBlackboardArtifactTag(BlackboardArtifact artifact, TagName tagName, String comment) throws TskCoreException { + BlackboardArtifactTag tag; + synchronized (this) { + lazyLoadExistingTagNames(); + tag = caseDb.addBlackboardArtifactTag(artifact, tagName, comment); } - BlackboardArtifactTag addBlackboardArtifactTag = tskCase.addBlackboardArtifactTag(artifact, tagName, comment); try { - Case.getCurrentCase().notifyBlackBoardArtifactTagAdded(addBlackboardArtifactTag); - } catch (IllegalStateException e) { - Logger.getLogger(TagsManager.class.getName()).log(Level.WARNING, NbBundle.getMessage(TagsManager.class, "TagsManager.addBlackboardArtifactTag.noCaseWarning")); + Case.getCurrentCase().notifyBlackBoardArtifactTagAdded(tag); + } catch (IllegalStateException ex) { + logger.log(Level.SEVERE, NbBundle.getMessage(TagsManager.class, "TagsManager.addBlackboardArtifactTag.noCaseWarning"), ex); } - return addBlackboardArtifactTag; + return tag; } /** @@ -414,19 +397,19 @@ public class TagsManager implements Closeable { * * @param tag The tag to delete. * - * @throws TskCoreException + * @throws TskCoreException If there is an error deleting the tag from the + * case database. */ - public synchronized void deleteBlackboardArtifactTag(BlackboardArtifactTag tag) throws TskCoreException { - // @@@ This is a work around to be removed when database access on the EDT is correctly synchronized. - if (!tagNamesInitialized) { - getExistingTagNames(); + public void deleteBlackboardArtifactTag(BlackboardArtifactTag tag) throws TskCoreException { + synchronized (this) { + lazyLoadExistingTagNames(); + caseDb.deleteBlackboardArtifactTag(tag); } - tskCase.deleteBlackboardArtifactTag(tag); try { Case.getCurrentCase().notifyBlackBoardArtifactTagDeleted(tag); - } catch (IllegalStateException e) { - Logger.getLogger(TagsManager.class.getName()).log(Level.WARNING, NbBundle.getMessage(TagsManager.class, "TagsManager.deleteBlackboardArtifactTag.noCaseWarning")); + } catch (IllegalStateException ex) { + logger.log(Level.WARNING, NbBundle.getMessage(TagsManager.class, "TagsManager.deleteBlackboardArtifactTag.noCaseWarning"), ex); } } @@ -435,15 +418,12 @@ public class TagsManager implements Closeable { * * @return A list, possibly empty, of blackboard artifact tags. * - * @throws TskCoreException + * @throws TskCoreException If there is an error getting the tags from the + * case database. */ - public List getAllBlackboardArtifactTags() throws TskCoreException { - // @@@ This is a work around to be removed when database access on the EDT is correctly synchronized. - if (!tagNamesInitialized) { - getExistingTagNames(); - } - - return tskCase.getAllBlackboardArtifactTags(); + public synchronized List getAllBlackboardArtifactTags() throws TskCoreException { + lazyLoadExistingTagNames(); + return caseDb.getAllBlackboardArtifactTags(); } /** @@ -454,15 +434,12 @@ public class TagsManager implements Closeable { * @return A count of the blackboard artifact tags with the specified tag * name. * - * @throws TskCoreException + * @throws TskCoreException If there is an error getting the tags count from + * the case database. */ public synchronized long getBlackboardArtifactTagsCountByTagName(TagName tagName) throws TskCoreException { - // @@@ This is a work around to be removed when database access on the EDT is correctly synchronized. - if (!tagNamesInitialized) { - getExistingTagNames(); - } - - return tskCase.getBlackboardArtifactTagsCountByTagName(tagName); + lazyLoadExistingTagNames(); + return caseDb.getBlackboardArtifactTagsCountByTagName(tagName); } /** @@ -472,15 +449,12 @@ public class TagsManager implements Closeable { * * @return the blackboard artifact tag with the specified tag id. * - * @throws TskCoreException + * @throws TskCoreException If there is an error getting the tag from the + * case database. */ public synchronized BlackboardArtifactTag getBlackboardArtifactTagByTagID(long tagID) throws TskCoreException { - // @@@ This is a work around to be removed when database access on the EDT is correctly synchronized. - if (!tagNamesInitialized) { - getExistingTagNames(); - } - - return tskCase.getBlackboardArtifactTagByID(tagID); + lazyLoadExistingTagNames(); + return caseDb.getBlackboardArtifactTagByID(tagID); } /** @@ -491,15 +465,12 @@ public class TagsManager implements Closeable { * @return A list, possibly empty, of the blackboard artifact tags with the * specified tag name. * - * @throws TskCoreException + * @throws TskCoreException If there is an error getting the tags from the + * case database. */ public synchronized List getBlackboardArtifactTagsByTagName(TagName tagName) throws TskCoreException { - // @@@ This is a work around to be removed when database access on the EDT is correctly synchronized. - if (!tagNamesInitialized) { - getExistingTagNames(); - } - - return tskCase.getBlackboardArtifactTagsByTagName(tagName); + lazyLoadExistingTagNames(); + return caseDb.getBlackboardArtifactTagsByTagName(tagName); } /** @@ -510,33 +481,43 @@ public class TagsManager implements Closeable { * @return A list, possibly empty, of the tags that have been applied to the * artifact. * - * @throws TskCoreException + * @throws TskCoreException If there is an error getting the tags from the + * case database. */ public synchronized List getBlackboardArtifactTagsByArtifact(BlackboardArtifact artifact) throws TskCoreException { - // @@@ This is a work around to be removed when database access on the EDT is correctly synchronized. - if (!tagNamesInitialized) { - getExistingTagNames(); - } - - return tskCase.getBlackboardArtifactTagsByArtifact(artifact); + lazyLoadExistingTagNames(); + return caseDb.getBlackboardArtifactTagsByArtifact(artifact); } + /** + * Saves the avaialble tag names to secondary storage. + */ @Override - public void close() throws IOException { + public synchronized void close() throws IOException { saveTagNamesToTagsSettings(); } - private void getExistingTagNames() { - getTagNamesFromCurrentCase(); - getTagNamesFromTagsSettings(); - getPredefinedTagNames(); - saveTagNamesToTagsSettings(); - tagNamesInitialized = true; // @@@ This is part of a work around to be removed when database access on the EDT is correctly synchronized. + /** + * Populates the tag names collection and the tag names table in the case + * database with the existing tag names from all sources. + */ + private void lazyLoadExistingTagNames() { + if (!tagNamesLoaded) { + addTagNamesFromCurrentCase(); + addTagNamesFromTagsSettings(); + addPredefinedTagNames(); + saveTagNamesToTagsSettings(); + tagNamesLoaded = true; + } } - private void getTagNamesFromCurrentCase() { + /** + * Adds any tag names that are in the case database to the tag names + * collection. + */ + private void addTagNamesFromCurrentCase() { try { - List currentTagNames = tskCase.getAllTagNames(); + List currentTagNames = caseDb.getAllTagNames(); for (TagName tagName : currentTagNames) { uniqueTagNames.put(tagName.getDisplayName(), tagName); } @@ -545,7 +526,12 @@ public class TagsManager implements Closeable { } } - private void getTagNamesFromTagsSettings() { + /** + * Adds any tag names that are in the properties file to the tag names + * collection and to the case database. The properties file is used to make + * it possible to use tag names across cases. + */ + private void addTagNamesFromTagsSettings() { String setting = ModuleSettings.getConfigSetting(TAGS_SETTINGS_NAME, TAG_NAMES_SETTING_KEY); if (null != setting && !setting.isEmpty()) { // Read the tag name setting and break it into tag name tuples. @@ -557,7 +543,7 @@ public class TagsManager implements Closeable { String[] tagNameAttributes = tagNameTuple.split(","); if (!uniqueTagNames.containsKey(tagNameAttributes[0])) { try { - TagName tagName = tskCase.addTagName(tagNameAttributes[0], tagNameAttributes[1], TagName.HTML_COLOR.getColorByName(tagNameAttributes[2])); + TagName tagName = caseDb.addTagName(tagNameAttributes[0], tagNameAttributes[1], TagName.HTML_COLOR.getColorByName(tagNameAttributes[2])); uniqueTagNames.put(tagName.getDisplayName(), tagName); } catch (TskCoreException ex) { Logger.getLogger(TagsManager.class.getName()).log(Level.SEVERE, "Failed to add saved tag name " + tagNameAttributes[0], ex); //NON-NLS @@ -567,18 +553,25 @@ public class TagsManager implements Closeable { } } - private void getPredefinedTagNames() { + /** + * Adds the standard tag names to the tag names collection. + */ + private void addPredefinedTagNames() { if (!uniqueTagNames.containsKey(NbBundle.getMessage(this.getClass(), "TagsManager.predefTagNames.bookmark.text"))) { try { - TagName tagName = tskCase.addTagName( + TagName tagName = caseDb.addTagName( NbBundle.getMessage(this.getClass(), "TagsManager.predefTagNames.bookmark.text"), "", TagName.HTML_COLOR.NONE); uniqueTagNames.put(tagName.getDisplayName(), tagName); } catch (TskCoreException ex) { - Logger.getLogger(TagsManager.class.getName()).log(Level.SEVERE, "Failed to add predefined 'Bookmark' tag name", ex); //NON-NLS + Logger.getLogger(TagsManager.class.getName()).log(Level.SEVERE, "Failed to add standard 'Bookmark' tag name to case database", ex); //NON-NLS } } } + /** + * Saves the tag names to a properties file. The properties file is used to + * make it possible to use tag names across cases. + */ private void saveTagNamesToTagsSettings() { if (!uniqueTagNames.isEmpty()) { StringBuilder setting = new StringBuilder(); @@ -593,4 +586,13 @@ public class TagsManager implements Closeable { ModuleSettings.setConfigSetting(TAGS_SETTINGS_NAME, TAG_NAMES_SETTING_KEY, setting.toString()); } } + + /** + * Exception thrown if there is an attempt to add a duplicate tag name. + */ + public static class TagNameAlreadyExistsException extends Exception { + + private static final long serialVersionUID = 1L; + } + } diff --git a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java index 70857146d4..a2267e0705 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java @@ -389,7 +389,11 @@ public class ServicesMonitor { */ @Override public void run() { - checkAllServices(); + try { + checkAllServices(); + } catch (Exception ex) { + logger.log(Level.SEVERE, "Unexpected exception in CrashDetectionTask", ex); //NON-NLS + } } } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DataSourceProcessor.java b/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DataSourceProcessor.java index 0d970049cf..8e81590231 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DataSourceProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DataSourceProcessor.java @@ -22,18 +22,24 @@ import javax.swing.JPanel; /** * Interface implemented by classes that add data sources of a particular type - * (e.g., images, local disks, virtual directories of local/logical files, etc.) - * to a case database. A data source processor is NOT responsible for analyzing - * the data source (running ingest modules on the data source and its contents). + * (e.g., images, local disks, virtual directories of local/logical files) to a + * case database. A data source processor is NOT responsible for analyzing the + * data source, i.e., running ingest modules on the data source and its + * contents. * * Data source processors plug in to the add data source wizard and should - * provide a JPanel to allow a user to select a data source and do any - * configuration the data source processor may require. The panel should support - * addition of the add data source wizard as a property change listener and - * should fire DSP_PANEL_EVENT property changes to communicate with the wizard. + * provide a UI panel to allow a user to select a data source and do any + * configuration required by the data source processor. The selection and + * configuration panel should support addition of the add data source wizard as + * a property change listener and should fire DSP_PANEL_EVENT property change + * events to communicate with the wizard. * - * Data source processors should perform all processing on a separate thread, - * reporting results using a callback object. + * Data source processors should perform all processing in a background task in + * a separate thread, reporting results using a callback object. + * + * It is recommended that implementers provide an overload of the run method + * that allows the data source processor to be run independently of the + * selection and configuration panel. */ public interface DataSourceProcessor { @@ -48,64 +54,76 @@ public interface DataSourceProcessor { enum DSP_PANEL_EVENT { /** - * Fire this event when the user changes something in the panel to - * notify the add data source wizard that it should call isPanelValid. + * This event is fired when the user changes something in the selection + * and configuration panel. It notifies the add data source wizard that + * it should call isPanelValid. */ UPDATE_UI, /** - * Fire this event to make the add data source wizard move focus to the - * next button. + * This event is fired to make the add data source wizard move focus to + * the wizard's next button. + * @deprecated Use UPDATE_UI. */ + @Deprecated FOCUS_NEXT }; /** * Gets a string that describes the type of data sources this processor is - * able to process. + * able to add to the case database. The string is suitable for display in a + * type selection UI component (e.g., a combo box). * - * @return A string suitable for display in a data source processor - * selection UI component (e.g., a combo box). + * @return A data source type display string for this data source processor. */ String getDataSourceType(); /** * Gets the panel that allows a user to select a data source and do any - * configuration the data source processor may require. + * configuration required by the data source. The panel is less than 544 + * pixels wide and less than 173 pixels high. * - * @return A JPanel less than 544 pixels wide and 173 pixels high. + * @return A selection and configuration panel for this data source + * processor. */ JPanel getPanel(); /** - * Indicates whether the settings in the panel are valid and complete. + * Indicates whether the settings in the selection and configuration panel + * are valid and complete. * * @return True if the settings are valid and complete and the processor is - * ready to have its run method called; false otherwise. + * ready to have its run method called, false otherwise. */ boolean isPanelValid(); /** - * Adds a data source to the case database using a separate thread and the - * settings provided by the panel. Returns as soon as the background task is - * started and uses the callback object to signal task completion and return - * results. + * Adds a data source to the case database using a background task in a + * separate thread and the settings provided by the selection and + * configuration panel. Returns as soon as the background task is started. + * The background task uses a callback object to signal task completion and + * return results. * - * NOTE: This method should not be called unless isPanelValid returns true. + * This method should not be called unless isPanelValid returns true. * - * @param progressMonitor Progress monitor for reporting progress during - * processing. - * @param callback Callback to call when processing is done. + * @param progressMonitor Progress monitor that will be used by the + * background task to report progress. + * @param callback Callback that will be used by the background task + * to return results. */ void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback); /** - * Requests cancellation of the data source processing task after it is - * started using the run method. Cancellation is not guaranteed. + * Requests cancellation of the background task that adds a data source to + * the case database, after the task is started using the run method. This + * is a "best effort" cancellation, with no guarantees that the case + * database will be unchanged. If cancellation succeeded, the list of new + * data sources returned by the background task will be empty. */ void cancel(); /** - * Resets the panel. + * Resets the selection and configuration panel for this data source + * processor. */ void reset(); } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DataSourceProcessorCallback.java b/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DataSourceProcessorCallback.java index 5c0f649d74..c248d33e24 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DataSourceProcessorCallback.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DataSourceProcessorCallback.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013-2014 Basis Technology Corp. + * Copyright 2013-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,56 +23,72 @@ import java.util.List; import org.sleuthkit.datamodel.Content; /** - * Abstract class for a callback for a DataSourceProcessor. - * - * Ensures that DSP invokes the caller overridden method, doneEDT(), in the EDT - * thread. + * An abstract base class for callback objects to be given to data source + * processors for use by the background tasks that add data sources to a case + * database. The callback objects are used to signal task completion and return + * results. * + * Concrete implementations of DataSourceProcessorCallback should override + * either the done method or the doneEDT method, but not both. */ public abstract class DataSourceProcessorCallback { public enum DataSourceProcessorResult { - NO_ERRORS, ///< No errors were encountered while ading the data source - CRITICAL_ERRORS, ///< No data was added to the database. There were fundamental errors processing the data (such as no data or system failure). - NONCRITICAL_ERRORS, ///< There was data added to the database, but there were errors from data corruption or a small number of minor issues. + /** + * No errors occurred while ading the data source to the case database. + */ + NO_ERRORS, + /** + * Critical errors occurred while ading the data source to the case + * database. The data source was not added to the case database. + */ + CRITICAL_ERRORS, + /** + * Non-critical errors occurred while adding the data source to the case + * database. The data source was added to the database, but the data + * source may have been corrupted in some way. + */ + NONCRITICAL_ERRORS }; /** - * Called by a DSP implementation when it is done adding a data source to - * the database. Users of the DSP can override this method if they do not - * want to be notified on the EDT. Otherwise, this method will call - * doneEDT() with the same arguments. + * Called by a data source processor when it is done adding a data source to + * the case database, this method adds a task to call the doneEDT method to + * the EDT task queue. * - * @param result Code for status - * @param errList List of error strings - * @param newContents List of root Content objects that were added to - * database. Typically only one is given. + * IMPORTANT: Concrete implementations of DataSourceProcessorCallback should + * override this method if the callback SHOULD NOT be done in the EDT. + * + * @param result Result code. + * @param errList List of error messages, possibly empty. + * @param newDataSources A list of the data sources added, empty if critical + * errors occurred or processing was successfully + * cancelled. */ - public void done(DataSourceProcessorResult result, List errList, List newContents) { - + public void done(DataSourceProcessorResult result, List errList, List newDataSources) { final DataSourceProcessorResult resultf = result; final List errListf = errList; - final List newContentsf = newContents; - - // Invoke doneEDT() that runs on the EDT . - EventQueue.invokeLater(new Runnable() { - @Override - public void run() { - doneEDT(resultf, errListf, newContentsf); - } + final List newContentsf = newDataSources; + EventQueue.invokeLater(() -> { + doneEDT(resultf, errListf, newContentsf); }); } /** - * Called by done() if the default implementation is used. Users of DSPs - * that have UI updates to do after the DSP is finished adding the DS can - * implement this method to receive the updates on the EDT. + * Called by a data source processor when it is done adding a data source to + * the case database, if the default done method has not been overridden. * - * @param result Code for status - * @param errList List of error strings - * @param newContents List of root Content objects that were added to - * database. Typically only one is given. + * IMPORTANT: Concrete implementations of DataSourceProcessorCallback should + * override the done method and provide an implementation of this method + * that throws an UnsupportedOperationException if the callback SHOULD NOT + * be done in the EDT. + * + * @param result Result code. + * @param errList List of error messages, possibly empty. + * @param newDataSources A list of the data sources added, empty if critical + * errors occurred or processing was successfully + * cancelled. */ - public abstract void doneEDT(DataSourceProcessorResult result, List errList, List newContents); + abstract public void doneEDT(DataSourceProcessorResult result, List errList, List newDataSources); }; diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AboutWindowPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/AboutWindowPanel.java index 04501c4c5b..3584cb5211 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AboutWindowPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AboutWindowPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -47,16 +47,22 @@ import org.sleuthkit.datamodel.SleuthkitJNI; */ public final class AboutWindowPanel extends JPanel implements HyperlinkListener { - private static final Logger Logger = org.sleuthkit.autopsy.coreutils.Logger.getLogger(AboutWindowPanel.class.getName()); - + private static final long serialVersionUID = 1L; private URL url = null; - - private Icon about; - + private final Icon about; private boolean verboseLogging; + public AboutWindowPanel() { + about = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/images/splash.png")); + init(); + } + public AboutWindowPanel(String pathToBrandingImage) { about = new ImageIcon(ImageUtilities.loadImage(pathToBrandingImage)); + init(); + } + + private void init() { initComponents(); logoLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); description.setText(org.openide.util.NbBundle.getMessage(AboutWindowPanel.class, @@ -67,8 +73,7 @@ public final class AboutWindowPanel extends JPanel implements HyperlinkListener copyright.setBackground(getBackground()); if (verboseLoggingIsSet()) { disableVerboseLoggingButton(); - } - + } } // //GEN-BEGIN:initComponents diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties index 2db3a4d69b..a0aeb51314 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties @@ -148,7 +148,7 @@ FXVideoPanel.progress.bufferingCancelled=media buffering was canceled FXVideoPanel.progress.bufferingInterrupted=media buffering was interrupted FXVideoPanel.progress.errorWritingVideoToDisk=Error writing video to disk OptionsCategory_Name_Multi_User_Settings=Multi-user -OptionsCategory_Keywords_Multi_User_Options=Multi-user Options +OptionsCategory_Keywords_Multi_User_Options=Multi-user Settings MultiUserSettingsPanel.lbSolrSettings.text=Solr Settings MultiUserSettingsPanel.cbEnableMultiUser.text=Enable Multi-user cases MultiUserSettingsPanel.lbDatabaseSettings.text=Database Settings diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java index 635a8b0e37..c7226483ef 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java @@ -488,7 +488,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat // if the artifact has an ASSOCIATED ARTIFACT, then we display the associated artifact instead try { for (BlackboardAttribute attr : artifact.getAttributes()) { - if (attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()) { + if (attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()) { long assocArtifactId = attr.getValueLong(); int assocArtifactIndex = -1; for (BlackboardArtifact art : artifacts) { diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java index 7ceb31f697..a3dc773abb 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewVideoPanel.java @@ -28,9 +28,7 @@ import java.util.TreeSet; import java.util.logging.Level; import javax.swing.JPanel; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; import org.sleuthkit.datamodel.AbstractFile; -import org.sleuthkit.datamodel.TskCoreException; /** * Video viewer part of the Media View layered pane. Uses different engines @@ -133,23 +131,18 @@ public abstract class MediaViewVideoPanel extends JPanel implements FrameCapture @Override public boolean isSupported(AbstractFile file) { + /* + * TODO (AUT-2042): Is this the logic we want? + */ String extension = file.getNameExtension(); - //TODO: is this what we want, to require both extension and mimetype support? if (AUDIO_EXTENSIONS.contains("." + extension) || getExtensionsList().contains("." + extension)) { SortedSet mimeTypes = new TreeSet<>(getMimeTypes()); - try { - String mimeType = new FileTypeDetector().getFileType(file); - if (nonNull(mimeType)) { - return mimeTypes.contains(mimeType); - } - } catch (FileTypeDetector.FileTypeDetectorInitException | TskCoreException ex) { - logger.log(Level.WARNING, "Failed to look up mimetype for " + file.getName() + " using FileTypeDetector. Fallingback on AbstractFile.isMimeType", ex); - if (!mimeTypes.isEmpty() && file.isMimeType(mimeTypes) == AbstractFile.MimeMatchEnum.TRUE) { - return true; - } + String mimeType = file.getMIMEType(); + if (nonNull(mimeType)) { + return mimeTypes.contains(mimeType); + } else { + return getExtensionsList().contains("." + extension); } - - return getExtensionsList().contains("." + extension); } return false; } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/TableFilterChildren.java b/Core/src/org/sleuthkit/autopsy/corecomponents/TableFilterChildren.java index bcb1657314..753483e42c 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/TableFilterChildren.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/TableFilterChildren.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,38 +23,67 @@ import org.openide.nodes.FilterNode; import org.openide.nodes.Node; /** - * Complementary class to TableFilterNode. + * A children (child factory) implementation for a TableFilterNode. A + * TableFilterNode creates at most one layer of child nodes for the node it + * wraps. It is designed to be used for nodes displayed in Autopsy table views. */ class TableFilterChildren extends FilterNode.Children { /** - * the constructor + * Constructs a children (child factory) implementation for a + * TableFilterNode. A TableFilterNode creates at most one layer of child + * nodes for the node it wraps. It is designed to be used for nodes + * displayed in Autopsy table views. + * + * @param wrappedNode The node wrapped by the TableFilterNode. */ - TableFilterChildren(Node arg) { - super(arg); - } - - @Override - protected Node copyNode(Node arg0) { - return new TableFilterNode(arg0, false); - } - - @Override - protected Node[] createNodes(Node arg0) { - // filter out the children - return new Node[]{this.copyNode(arg0)}; + TableFilterChildren(Node wrappedNode) { + super(wrappedNode); } /** - * Converts the given FsContent into "Children". + * Copies a TableFilterNode, with the create children (child factory) flag + * set to false. * - * @param fs + * @param nodeToCopy The TableFilterNode to copy. * - * @return children + * @return A copy of a TableFilterNode. */ - public static Children createInstance(Node arg, boolean createChild) { - if (createChild) { - return new TableFilterChildren(arg); + @Override + protected Node copyNode(Node nodeToCopy) { + return new TableFilterNode(nodeToCopy, false); + } + + /** + * Creates the child nodes represented by this children (child factory) + * object. + * + * @param key The key, i.e., the node, for which to create the child nodes. + * + * @return + */ + @Override + protected Node[] createNodes(Node key) { + return new Node[]{this.copyNode(key)}; + } + + /** + * Creates a children (child factory) object for a node wrapped in a + * TableFilterNode. A TableFilterNode creates at most one layer of child + * nodes for the node it wraps. It is designed to be used for nodes + * displayed in Autopsy table views. + * + * + * @param wrappedNode The node wrapped by the TableFilterNode. + * @param createChildren True if a children (child factory) object should be + * created for the wrapped node. + * + * @return A children (child factory) object for a node wrapped by a + * TableFilterNode. + */ + public static Children createInstance(Node wrappedNode, boolean createChildren) { + if (createChildren) { + return new TableFilterChildren(wrappedNode); } else { return Children.LEAF; } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/TableFilterNode.java b/Core/src/org/sleuthkit/autopsy/corecomponents/TableFilterNode.java index 11caf66c75..9a524bcbd3 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/TableFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/TableFilterNode.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,48 +23,40 @@ import org.openide.nodes.Node; import org.openide.util.NbBundle; /** - * This class is used to filter the nodes that we want to show on the - * "TreeTableView". So basically we just want to show one layer of nodes from - * it's parent. - * - * @author jantonius + * A filter node that creates at most one layer of child nodes for the node it + * wraps. It is designed to be used for nodes displayed in Autopsy table views. */ public class TableFilterNode extends FilterNode { - private boolean createChild; - private String itemType; + private final boolean createChildren; /** - * the constructor - */ - public TableFilterNode(Node arg, boolean crChild) { - super(arg, TableFilterChildren.createInstance(arg, crChild)); - this.createChild = crChild; - this.itemType = ""; - } - - public TableFilterNode(Node arg, boolean crChild, String itemType) { - super(arg, TableFilterChildren.createInstance(arg, crChild)); - this.createChild = crChild; - this.itemType = itemType; - } - - /** - * Override the display name / header for the first (tree) column on the - * "TreeTableView". + * Constructs a filter node that creates at most one layer of child nodes + * for the node it wraps. It is designed to be used for nodes displayed in + * Autopsy table views. * - * @return disName the display name for the first column + * @param wrappedNode The node to wrap in the filter node. + * @param createChildren True if a children (child factory) object should be + * created for the wrapped node. + */ + public TableFilterNode(Node wrappedNode, boolean createChildren) { + super(wrappedNode, TableFilterChildren.createInstance(wrappedNode, createChildren)); + this.createChildren = createChildren; + } + + /** + * Returns a display name for the wrapped node, for use in the first column + * of an Autopsy table view. + * + * @return The display name. */ @Override public String getDisplayName() { - if (createChild) { + if (createChildren) { return NbBundle.getMessage(this.getClass(), "TableFilterNode.displayName.text"); } else { return super.getDisplayName(); } } - - public String getItemType() { - return itemType; - } + } diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java b/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java index 4e627ea09d..f6e87d22e5 100755 --- a/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java @@ -149,8 +149,8 @@ public class ImageUtils { /** * thread that saves generated thumbnails to disk in the background */ - private static final Executor imageSaver = - Executors.newSingleThreadExecutor(new BasicThreadFactory.Builder() + private static final Executor imageSaver + = Executors.newSingleThreadExecutor(new BasicThreadFactory.Builder() .namingPattern("icon saver-%d").build()); //NOI18N NON-NLS public static List getSupportedImageExtensions() { @@ -223,40 +223,19 @@ public class ImageUtils { } /** - * Does the image have a GIF mimetype. + * Checks the MIME type of a file to determine whether it is a GIF. If the + * MIME type is not known, checks for a "gif" extension. * - * @param file + * @param file The file to be checked. * - * @return true if the given file has a GIF mimetype + * @return True or false */ public static boolean isGIF(AbstractFile file) { - try { - final FileTypeDetector myFileTypeDetector = getFileTypeDetector(); - if (nonNull(myFileTypeDetector)) { - String fileType = myFileTypeDetector.getFileType(file); - return IMAGE_GIF_MIME.equalsIgnoreCase(fileType); - } - } catch (FileTypeDetectorInitException ex) { - LOGGER.log(Level.WARNING, "Failed to initialize FileTypeDetector.", ex); //NOI18N NON-NLS - } catch (TskCoreException ex) { - if (ex.getMessage().contains("An SQLException was provoked by the following failure: java.lang.InterruptedException")) { //NON-NLS - LOGGER.log(Level.WARNING, "Mime type look up with FileTypeDetector was interupted."); //NOI18N} NON-NLS - return "gif".equalsIgnoreCase(file.getNameExtension()); //NOI18N - } else { - LOGGER.log(Level.SEVERE, "Failed to get mime type of " + getContentPathSafe(file) + " with FileTypeDetector.", ex); //NOI18N} NON-NLS - } - } - LOGGER.log(Level.WARNING, "Falling back on direct mime type check for {0}.", getContentPathSafe(file)); //NOI18N NON-NLS - switch (file.isMimeType(GIF_MIME_SET)) { - - case TRUE: - return true; - case UNDEFINED: - LOGGER.log(Level.WARNING, "Falling back on extension check."); //NOI18N NON-NLS - return "gif".equalsIgnoreCase(file.getNameExtension()); //NOI18N - case FALSE: - default: - return false; + String mimeType = file.getMIMEType(); + if (nonNull(mimeType)) { + return IMAGE_GIF_MIME.equalsIgnoreCase(mimeType); + } else { + return "gif".equalsIgnoreCase(file.getNameExtension()); //NOI18N } } @@ -283,25 +262,15 @@ public class ImageUtils { if (file.getSize() == 0) { return false; } - final String extension = file.getNameExtension(); - try { - String mimeType = getFileTypeDetector().getFileType(file); - if (Objects.nonNull(mimeType)) { - return supportedMimeTypes.contains(mimeType) - || (conditionalMimes.contains(mimeType.toLowerCase()) && supportedExtension.contains(extension)); - } - } catch (FileTypeDetector.FileTypeDetectorInitException | TskCoreException ex) { - LOGGER.log(Level.WARNING, "Failed to look up mimetype for {0} using FileTypeDetector:{1}", new Object[]{getContentPathSafe(file), ex.toString()}); //NOI18N NON-NLS - LOGGER.log(Level.INFO, "Falling back on AbstractFile.isMimeType"); //NOI18N NON-NLS - AbstractFile.MimeMatchEnum mimeMatch = file.isMimeType(supportedMimeTypes); - if (mimeMatch == AbstractFile.MimeMatchEnum.TRUE) { - return true; - } else if (mimeMatch == AbstractFile.MimeMatchEnum.FALSE) { - return false; - } + String mimeType = file.getMIMEType(); + String extension = file.getNameExtension(); + if (nonNull(mimeType)) { + return supportedMimeTypes.contains(mimeType) + || (conditionalMimes.contains(mimeType.toLowerCase()) + && supportedExtension.contains(extension)); + } else { + return StringUtils.isNotBlank(extension) && supportedExtension.contains(extension); } - // if we have an extension, check it - return StringUtils.isNotBlank(extension) && supportedExtension.contains(extension); } /** @@ -934,7 +903,7 @@ public class ImageUtils { * * @return */ - static String getContentPathSafe(Content content) { + static String getContentPathSafe(Content content) { try { return content.getUniquePath(); } catch (TskCoreException tskCoreException) { diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ArtifactStringContent.java b/Core/src/org/sleuthkit/autopsy/datamodel/ArtifactStringContent.java index 502a7828a4..db8607cd93 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ArtifactStringContent.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ArtifactStringContent.java @@ -72,19 +72,19 @@ public class ArtifactStringContent implements StringContent { // name column buffer.append(""); //NON-NLS - buffer.append(attr.getAttributeTypeDisplayName()); + buffer.append(attr.getAttributeType().getDisplayName()); buffer.append(""); //NON-NLS // value column buffer.append(""); //NON-NLS - if (attr.getAttributeTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID() - || attr.getAttributeTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID() - || attr.getAttributeTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_CREATED.getTypeID() - || attr.getAttributeTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_MODIFIED.getTypeID() - || attr.getAttributeTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_RCVD.getTypeID() - || attr.getAttributeTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_SENT.getTypeID() - || attr.getAttributeTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_START.getTypeID() - || attr.getAttributeTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_END.getTypeID()) { + if (attr.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID() + || attr.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID() + || attr.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_CREATED.getTypeID() + || attr.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_MODIFIED.getTypeID() + || attr.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_RCVD.getTypeID() + || attr.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_SENT.getTypeID() + || attr.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_START.getTypeID() + || attr.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_END.getTypeID()) { long epoch = attr.getValueLong(); String time = "0000-00-00 00:00:00"; if (epoch != 0) { @@ -93,7 +93,7 @@ public class ArtifactStringContent implements StringContent { } buffer.append(time); } else { - switch (attr.getValueType()) { + switch (attr.getAttributeType().getValueType()) { case STRING: String str = attr.getValueString(); str = str.replaceAll(" ", " "); //NON-NLS @@ -117,7 +117,7 @@ public class ArtifactStringContent implements StringContent { case DATETIME: buffer.append(attr.getValueLong()); break; - + } } if (!"".equals(attr.getContext())) { diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java index 198baaf923..7101b3c023 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java @@ -117,7 +117,7 @@ public class BlackboardArtifactNode extends DisplayableItemNode { if (artifact != null && artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) { try { for (BlackboardAttribute attribute : artifact.getAttributes()) { - if (attribute.getAttributeTypeID() == ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()) { + if (attribute.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()) { BlackboardArtifact associatedArtifact = Case.getCurrentCase().getSleuthkitCase().getBlackboardArtifact(attribute.getValueLong()); if (associatedArtifact != null) { displayName = associatedArtifact.getDisplayName() + " Artifact"; // NON-NLS @@ -171,7 +171,7 @@ public class BlackboardArtifactNode extends DisplayableItemNode { AbstractFile af = (AbstractFile) associated; ext = af.getNameExtension(); actualMimeType = af.getMIMEType(); - if(actualMimeType == null) { + if (actualMimeType == null) { actualMimeType = ""; } } @@ -179,11 +179,11 @@ public class BlackboardArtifactNode extends DisplayableItemNode { NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.ext.displayName"), NO_DESCR, ext)); - ss.put(new NodeProperty<>( - NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.mimeType.name"), - NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.mimeType.displayName"), - NO_DESCR, - actualMimeType)); + ss.put(new NodeProperty<>( + NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.mimeType.name"), + NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.mimeType.displayName"), + NO_DESCR, + actualMimeType)); } if (Arrays.asList(SHOW_UNIQUE_PATH).contains(artifactTypeId)) { @@ -282,8 +282,8 @@ public class BlackboardArtifactNode extends DisplayableItemNode { /** * Fill map with Artifact properties * - * @param map map with preserved ordering, where property names/values are - * put + * @param map map with preserved ordering, where property names/values + * are put * @param artifact to extract properties from */ @SuppressWarnings("deprecation") // TODO: Remove this when TSK_TAGGED_ARTIFACT rows are removed in a database upgrade. @@ -384,7 +384,7 @@ public class BlackboardArtifactNode extends DisplayableItemNode { String keyword = null; String regexp = null; for (BlackboardAttribute att : attributes) { - final int attributeTypeID = att.getAttributeTypeID(); + final int attributeTypeID = att.getAttributeType().getTypeID(); if (attributeTypeID == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()) { keyword = att.getValueString(); } else if (attributeTypeID == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getTypeID()) { diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java index e4c34ebce9..52b1954188 100755 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java @@ -271,8 +271,8 @@ public class DataResultFilterNode extends FilterNode { Content c = null; try { for (BlackboardAttribute attr : art.getAttributes()) { - if (attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()) { - switch (attr.getValueType()) { + if (attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()) { + switch (attr.getAttributeType().getValueType()) { case INTEGER: int i = attr.getValueInt(); if (i != -1) { diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java index cabc5cc3d4..57de4e760e 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java @@ -865,7 +865,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat String setName = null; List attributes = art.getAttributes(); for (BlackboardAttribute att : attributes) { - int typeId = att.getAttributeTypeID(); + int typeId = att.getAttributeType().getTypeID(); if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()) { setName = att.getValueString(); } @@ -882,7 +882,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat String keywordName = null; List attributes = art.getAttributes(); for (BlackboardAttribute att : attributes) { - int typeId = att.getAttributeTypeID(); + int typeId = att.getAttributeType().getTypeID(); if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()) { listName = att.getValueString(); } else if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()) { @@ -909,7 +909,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat String setName = null; List attributes = art.getAttributes(); for (BlackboardAttribute att : attributes) { - int typeId = att.getAttributeTypeID(); + int typeId = att.getAttributeType().getTypeID(); if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()) { setName = att.getValueString(); } diff --git a/Core/src/org/sleuthkit/autopsy/events/AutopsyEventPublisher.java b/Core/src/org/sleuthkit/autopsy/events/AutopsyEventPublisher.java index 6b679415f9..5fe17a57ef 100644 --- a/Core/src/org/sleuthkit/autopsy/events/AutopsyEventPublisher.java +++ b/Core/src/org/sleuthkit/autopsy/events/AutopsyEventPublisher.java @@ -40,7 +40,7 @@ public final class AutopsyEventPublisher { * Composed of thread-safe objects. */ private static final Logger logger = Logger.getLogger(AutopsyEventPublisher.class.getName()); - private static final int MAX_REMOTE_EVENT_PUBLISH_TRIES = 3; + private static final int MAX_REMOTE_EVENT_PUBLISH_TRIES = 1; private final LocalEventPublisher localPublisher; private RemoteEventPublisher remotePublisher; private String currentChannelName; @@ -86,15 +86,8 @@ public final class AutopsyEventPublisher { * events from other Autopsy nodes. */ public void closeRemoteEventChannel() { + stopRemotePublisher(); currentChannelName = null; - if (null != remotePublisher) { - try { - remotePublisher.stop(); - } catch (JMSException ex) { - logger.log(Level.SEVERE, "Error closing remote event channel", ex); //NON-NLS - } - remotePublisher = null; - } } /** @@ -162,12 +155,10 @@ public final class AutopsyEventPublisher { * @param event The event to publish. */ public void publishRemotely(AutopsyEvent event) { - /* - * This is a no-op if a remote channel has not been opened. - */ if (null != currentChannelName) { boolean published = false; int tryCount = 1; + while (false == published && tryCount <= MAX_REMOTE_EVENT_PUBLISH_TRIES) { try { if (null == remotePublisher) { @@ -175,16 +166,28 @@ public final class AutopsyEventPublisher { } remotePublisher.publish(event); published = true; - } catch (JMSException ex) { + } catch (AutopsyEventException | JMSException ex) { logger.log(Level.SEVERE, String.format("Failed to publish %s using channel %s (tryCount = %s)", event.getPropertyName(), currentChannelName, tryCount), ex); //NON-NLS - closeRemoteEventChannel(); - ++tryCount; - } catch (AutopsyEventException ex) { - logger.log(Level.SEVERE, String.format("Failed to reopen channel %s to publish %s event (tryCount = %s)", currentChannelName, event.getPropertyName(), tryCount), ex); //NON-NLS + stopRemotePublisher(); ++tryCount; } } - } + } + } + + /** + * Stops the remote event publisher, but does not reset the current channel + * name. + */ + private void stopRemotePublisher() { + if (null != remotePublisher) { + try { + remotePublisher.stop(); + } catch (JMSException ex) { + logger.log(Level.SEVERE, String.format("Error closing remote event publisher for channel %s", currentChannelName), ex); //NON-NLS + } + remotePublisher = null; + } } } diff --git a/Core/src/org/sleuthkit/autopsy/events/MessageServiceConnectionInfo.java b/Core/src/org/sleuthkit/autopsy/events/MessageServiceConnectionInfo.java index 9db745b09b..f7cf28096d 100644 --- a/Core/src/org/sleuthkit/autopsy/events/MessageServiceConnectionInfo.java +++ b/Core/src/org/sleuthkit/autopsy/events/MessageServiceConnectionInfo.java @@ -144,7 +144,7 @@ public final class MessageServiceConnectionInfo { } catch (JMSException ex) { String result; Throwable cause = ex.getCause(); - if (cause != null) { + if (null != cause && null != cause.getMessage()) { // there is more information from another exception String msg = cause.getMessage(); if (msg.startsWith(CONNECTION_TIMED_OUT)) { diff --git a/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties b/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties index ba1e445d8a..ad71c7e523 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties @@ -115,5 +115,5 @@ IngestJob.cancelReason.notCancelled.text=Not cancelled IngestJob.cancelReason.cancelledByUser.text=Cancelled by user IngestJob.cancelReason.ingestModStartFail.text=Ingest modules startup failed IngestJob.cancelReason.outOfDiskSpace.text=Out of disk space -IngestJob.cancelReason.servicesDown.text=Not cancelled +IngestJob.cancelReason.servicesDown.text=Services Down IngestJob.cancelReason.caseClosed.text=Case closed diff --git a/Core/src/org/sleuthkit/autopsy/ingest/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/ingest/Bundle_ja.properties index b11134b1ac..68034d6409 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/ingest/Bundle_ja.properties @@ -1,116 +1,115 @@ -CTL_IngestMessageTopComponent=\u30E1\u30C3\u30BB\u30FC\u30B8 -HINT_IngestMessageTopComponent=\u30E1\u30C3\u30BB\u30FC\u30B8\u30A6\u30A3\u30F3\u30C9\u30A6 -IngestDialog.closeButton.title=\u9589\u3058\u308B -IngestDialog.startButton.title=\u958B\u59CB -IngestDialog.title.text=\u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8 -IngestJob.progress.cancelling={0}\uFF08\u30AD\u30E3\u30F3\u30BB\u30EB\u4E2D\u2026\uFF09 -IngestJob.progress.dataSourceIngest.displayName={1}\u306E{0} -IngestJob.progress.fileIngest.displayName={0}\u306E\u30D5\u30A1\u30A4\u30EB\u3092\u89E3\u6790\u4E2D -IngestManager.moduleErr=\u30E2\u30B8\u30E5\u30FC\u30EB\u30A8\u30E9\u30FC -IngestManager.moduleErr.errListenToUpdates.msg=Ingest Manager\u30A2\u30C3\u30D7\u30C7\u30FC\u30C8\u3092\u78BA\u8A8D\u4E2D\u306B\u30E2\u30B8\u30E5\u30FC\u30EB\u304C\u30A8\u30E9\u30FC\u3092\u8D77\u3053\u3057\u307E\u3057\u305F\u3002\u3069\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u304B\u30ED\u30B0\u3092\u78BA\u8A8D\u3057\u3066\u4E0B\u3055\u3044\u3002\u4E00\u90E8\u306E\u30C7\u30FC\u30BF\u304C\u4E0D\u5B8C\u5168\u304B\u3082\u3057\u308C\u307E\u305B\u3093\u3002 -IngestManager.StartIngestJobsTask.run.cancelling={0}\uFF08\u30AD\u30E3\u30F3\u30BB\u30EB\u4E2D\u2026\uFF09 -IngestManager.StartIngestJobsTask.run.displayName=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u958B\u59CB\u4E2D -IngestMessage.exception.srcSubjDetailsDataNotNull.msg=\u30BD\u30FC\u30B9\u3001\u30B5\u30D6\u30B8\u30A7\u30AF\u30C8\u3001\u8A73\u7D30\u304A\u3088\u3073\u30C7\u30FC\u30BF\u306F\u30CC\u30EB\u3067\u306F\u3044\u3051\u307E\u305B\u3093 -IngestMessage.exception.srcSubjNotNull.msg=\u30BD\u30FC\u30B9\u304A\u3088\u3073\u30B5\u30D6\u30B8\u30A7\u30AF\u30C8\u306F\u30CC\u30EB\u3067\u306F\u3044\u3051\u307E\u305B\u3093 -IngestMessage.exception.typeSrcSubjNotNull.msg=\u30E1\u30C3\u30BB\u30FC\u30B8\u30BF\u30A4\u30D7\u3001\u30BD\u30FC\u30B9\u304A\u3088\u3073\u30B5\u30D6\u30B8\u30A7\u30AF\u30C8\u306F\u30CC\u30EB\u3067\u306F\u3044\u3051\u307E\u305B\u3093 -IngestMessage.toString.data.text=\ \u30C7\u30FC\u30BF\uFF1A{0} -IngestMessage.toString.date.text=\ \u65E5\u4ED8\uFF1A{0} -IngestMessage.toString.details.text=\ \u8A73\u7D30\uFF1A{0} -IngestMessage.toString.subject.text=\ \u30B5\u30D6\u30B8\u30A7\u30AF\u30C8\uFF1A{0} -IngestMessage.toString.type.text=\u30BF\u30A4\u30D7\uFF1A{0} -IngestMessageDetailsPanel.copyMenuItem.text=\u30B3\u30D4\u30FC -IngestMessageDetailsPanel.messageDetailsPane.contentType=\u30C6\u30AD\u30B9\u30C8\uFF0Fhtml -IngestMessageDetailsPanel.selectAllMenuItem.text=\u3059\u3079\u3066\u9078\u629E -IngestMessageDetailsPanel.viewArtifactButton.text=\u7D50\u679C\u3078\u79FB\u52D5 -IngestMessageDetailsPanel.viewContentButton.text=\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3078\u79FB\u52D5 -IngestMessagePanel.BooleanRenderer.exception.nonBoolVal.msg=\u30D6\u30FC\u30EB\u5024\u3067\u306F\u306A\u3044\u3082\u306E\u306BBooleanRenderer\u3092\u4F7F\u7528\u3057\u3088\u3046\u3068\u3057\u307E\u3057\u305F\u3002 -IngestMessagePanel.DateRenderer.exception.nonDateVal.text=\u65E5\u4ED8\u3067\u306F\u306A\u3044\u3082\u306E\u306BDateRenderer\u3092\u4F7F\u7528\u3057\u3088\u3046\u3068\u3057\u307E\u3057\u305F\u3002 -IngestMessagePanel.moduleErr=\u30E2\u30B8\u30E5\u30FC\u30EB\u30A8\u30E9\u30FC -IngestMessagePanel.moduleErr.errListenUpdates.text=IngestMessagePanel\u30A2\u30C3\u30D7\u30C7\u30FC\u30C8\u3092\u78BA\u8A8D\u4E2D\u306B\u30E2\u30B8\u30E5\u30FC\u30EB\u304C\u30A8\u30E9\u30FC\u3092\u8D77\u3053\u3057\u307E\u3057\u305F\u3002\u3069\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u304B\u30ED\u30B0\u3092\u78BA\u8A8D\u3057\u3066\u4E0B\u3055\u3044\u3002\u4E00\u90E8\u306E\u30C7\u30FC\u30BF\u304C\u4E0D\u5B8C\u5168\u304B\u3082\u3057\u308C\u307E\u305B\u3093\u3002 -IngestMessagePanel.MsgTableMod.colNames.module=\u30E2\u30B8\u30E5\u30FC\u30EB -IngestMessagePanel.MsgTableMod.colNames.new=\u65B0\u898F\uFF1F -IngestMessagePanel.MsgTableMod.colNames.num=\u756A\u53F7 -IngestMessagePanel.MsgTableMod.colNames.subject=\u30B5\u30D6\u30B8\u30A7\u30AF\u30C8 -IngestMessagePanel.MsgTableMod.colNames.timestamp=\u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7 -IngestMessagePanel.sortByComboBox.model.priority=\u512A\u5148\u5EA6 +CTL_IngestMessageTopComponent=\u30e1\u30c3\u30bb\u30fc\u30b8 +HINT_IngestMessageTopComponent=\u30e1\u30c3\u30bb\u30fc\u30b8\u30a6\u30a3\u30f3\u30c9\u30a6 +IngestDialog.closeButton.title=\u9589\u3058\u308b +IngestDialog.startButton.title=\u958b\u59cb +IngestDialog.title.text=\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8 +IngestJob.progress.cancelling={0}\uff08\u30ad\u30e3\u30f3\u30bb\u30eb\u4e2d\u2026\uff09 +IngestJob.progress.dataSourceIngest.displayName={1}\u306e{0} +IngestJob.progress.fileIngest.displayName={0}\u306e\u30d5\u30a1\u30a4\u30eb\u3092\u89e3\u6790\u4e2d +IngestManager.moduleErr=\u30e2\u30b8\u30e5\u30fc\u30eb\u30a8\u30e9\u30fc +IngestManager.moduleErr.errListenToUpdates.msg=Ingest Manager\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u3092\u78ba\u8a8d\u4e2d\u306b\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u30a8\u30e9\u30fc\u3092\u8d77\u3053\u3057\u307e\u3057\u305f\u3002\u3069\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u304b\u30ed\u30b0\u3092\u78ba\u8a8d\u3057\u3066\u4e0b\u3055\u3044\u3002\u4e00\u90e8\u306e\u30c7\u30fc\u30bf\u304c\u4e0d\u5b8c\u5168\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002 +IngestManager.StartIngestJobsTask.run.cancelling={0}\uff08\u30ad\u30e3\u30f3\u30bb\u30eb\u4e2d\u2026\uff09 +IngestManager.StartIngestJobsTask.run.displayName=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u958b\u59cb\u4e2d +IngestMessage.exception.srcSubjDetailsDataNotNull.msg=\u30bd\u30fc\u30b9\u3001\u30b5\u30d6\u30b8\u30a7\u30af\u30c8\u3001\u8a73\u7d30\u304a\u3088\u3073\u30c7\u30fc\u30bf\u306f\u30cc\u30eb\u3067\u306f\u3044\u3051\u307e\u305b\u3093 +IngestMessage.exception.srcSubjNotNull.msg=\u30bd\u30fc\u30b9\u304a\u3088\u3073\u30b5\u30d6\u30b8\u30a7\u30af\u30c8\u306f\u30cc\u30eb\u3067\u306f\u3044\u3051\u307e\u305b\u3093 +IngestMessage.exception.typeSrcSubjNotNull.msg=\u30e1\u30c3\u30bb\u30fc\u30b8\u30bf\u30a4\u30d7\u3001\u30bd\u30fc\u30b9\u304a\u3088\u3073\u30b5\u30d6\u30b8\u30a7\u30af\u30c8\u306f\u30cc\u30eb\u3067\u306f\u3044\u3051\u307e\u305b\u3093 +IngestMessage.toString.data.text=\ \u30c7\u30fc\u30bf\uff1a{0} +IngestMessage.toString.date.text=\ \u65e5\u4ed8\uff1a{0} +IngestMessage.toString.details.text=\ \u8a73\u7d30\uff1a{0} +IngestMessage.toString.subject.text=\ \u30b5\u30d6\u30b8\u30a7\u30af\u30c8\uff1a{0} +IngestMessage.toString.type.text=\u30bf\u30a4\u30d7\uff1a{0} +IngestMessageDetailsPanel.copyMenuItem.text=\u30b3\u30d4\u30fc +IngestMessageDetailsPanel.messageDetailsPane.contentType=\u30c6\u30ad\u30b9\u30c8\uff0fhtml +IngestMessageDetailsPanel.selectAllMenuItem.text=\u3059\u3079\u3066\u9078\u629e +IngestMessageDetailsPanel.viewArtifactButton.text=\u7d50\u679c\u3078\u79fb\u52d5 +IngestMessageDetailsPanel.viewContentButton.text=\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3078\u79fb\u52d5 +IngestMessagePanel.BooleanRenderer.exception.nonBoolVal.msg=\u30d6\u30fc\u30eb\u5024\u3067\u306f\u306a\u3044\u3082\u306e\u306bBooleanRenderer\u3092\u4f7f\u7528\u3057\u3088\u3046\u3068\u3057\u307e\u3057\u305f\u3002 +IngestMessagePanel.DateRenderer.exception.nonDateVal.text=\u65e5\u4ed8\u3067\u306f\u306a\u3044\u3082\u306e\u306bDateRenderer\u3092\u4f7f\u7528\u3057\u3088\u3046\u3068\u3057\u307e\u3057\u305f\u3002 +IngestMessagePanel.moduleErr=\u30e2\u30b8\u30e5\u30fc\u30eb\u30a8\u30e9\u30fc +IngestMessagePanel.moduleErr.errListenUpdates.text=IngestMessagePanel\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u3092\u78ba\u8a8d\u4e2d\u306b\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u30a8\u30e9\u30fc\u3092\u8d77\u3053\u3057\u307e\u3057\u305f\u3002\u3069\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u304b\u30ed\u30b0\u3092\u78ba\u8a8d\u3057\u3066\u4e0b\u3055\u3044\u3002\u4e00\u90e8\u306e\u30c7\u30fc\u30bf\u304c\u4e0d\u5b8c\u5168\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002 +IngestMessagePanel.MsgTableMod.colNames.module=\u30e2\u30b8\u30e5\u30fc\u30eb +IngestMessagePanel.MsgTableMod.colNames.new=\u65b0\u898f\uff1f +IngestMessagePanel.MsgTableMod.colNames.num=\u756a\u53f7 +IngestMessagePanel.MsgTableMod.colNames.subject=\u30b5\u30d6\u30b8\u30a7\u30af\u30c8 +IngestMessagePanel.MsgTableMod.colNames.timestamp=\u30bf\u30a4\u30e0\u30b9\u30bf\u30f3\u30d7 +IngestMessagePanel.sortByComboBox.model.priority=\u512a\u5148\u5ea6 IngestMessagePanel.sortByComboBox.model.time=\u6642\u9593 -IngestMessagePanel.sortByComboBox.toolTipText=\u6642\u9593\u9806\uFF08\u6642\u7CFB\u5217\uFF09\u307E\u305F\u306F\u30E1\u30C3\u30BB\u30FC\u30B8\u306E\u512A\u5148\u5EA6\u3067\u30BD\u30FC\u30C8 -IngestMessagePanel.sortByLabel.text=\u6B21\u3067\u30BD\u30FC\u30C8\uFF1A -IngestMessagePanel.totalMessagesNameLabel.text=\u5408\u8A08\uFF1A +IngestMessagePanel.sortByComboBox.toolTipText=\u6642\u9593\u9806\uff08\u6642\u7cfb\u5217\uff09\u307e\u305f\u306f\u30e1\u30c3\u30bb\u30fc\u30b8\u306e\u512a\u5148\u5ea6\u3067\u30bd\u30fc\u30c8 +IngestMessagePanel.sortByLabel.text=\u6b21\u3067\u30bd\u30fc\u30c8\uff1a +IngestMessagePanel.totalMessagesNameLabel.text=\u5408\u8a08\uff1a IngestMessagePanel.totalMessagesNameVal.text=- -IngestMessagePanel.totalUniqueMessagesNameLabel.text=\u30E6\u30CB\u30FC\u30AF\uFF1A +IngestMessagePanel.totalUniqueMessagesNameLabel.text=\u30e6\u30cb\u30fc\u30af\uff1a IngestMessagePanel.totalUniqueMessagesNameVal.text=- -IngestMessagesToolbar.customizeButton.toolTipText=\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8 -IngestMessageTopComponent.displayName=\u30A4\u30F3\u30DC\u30C3\u30AF\u30B9\u3092\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8 -IngestMessageTopComponent.displayReport.option.GenRpt=\u30EC\u30DD\u30FC\u30C8\u3092\u751F\u6210 +IngestMessagesToolbar.customizeButton.toolTipText=\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8 +IngestMessageTopComponent.displayName=\u30a4\u30f3\u30dc\u30c3\u30af\u30b9\u3092\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8 +IngestMessageTopComponent.displayReport.option.GenRpt=\u30ec\u30dd\u30fc\u30c8\u3092\u751f\u6210 IngestMessageTopComponent.displayReport.option.OK=OK -IngestMessageTopComponent.initComponents.name=\u30A4\u30F3\u30DC\u30C3\u30AF\u30B9\u3092\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8 -IngestMessageTopComponent.msgDlg.ingestRpt.text=\u30EC\u30DD\u30FC\u30C8\u3092\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8 -IngestMonitor.mgrErrMsg.lowDiskSpace.msg=\u30C7\u30A3\u30B9\u30AF{0}\u306E\u30C7\u30A3\u30B9\u30AF\u9818\u57DF\u4E0D\u8DB3\u306E\u305F\u3081\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u3092\u4E2D\u6B62\u3057\u307E\u3059\u3002\n\u30B1\u30FC\u30B9\u30C9\u30E9\u30A4\u30D6\u306B\u6700\u4F4E1GB\u306E\u7A7A\u304D\u9818\u57DF\u304C\u3042\u308B\u306E\u3092\u78BA\u8A8D\u3057\u3001\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u3092\u518D\u5B9F\u884C\u3057\u3066\u4E0B\u3055\u3044\u3002 -IngestMonitor.mgrErrMsg.lowDiskSpace.title=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u304C\u4E2D\u6B62\u3055\u308C\u307E\u3057\u305F\u30FC{0}\u306E\u30C7\u30A3\u30B9\u30AF\u9818\u57DF\u4E0D\u8DB3 -OpenIDE-Module-Name=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8 -IngestManager.StartIngestJobsTask.run.startupErr.dlgErrorList=\n\u30A8\u30E9\u30FC\uFF1A\n{0} -IngestManager.StartIngestJobsTask.run.startupErr.dlgMsg=\u5358\u6570\u307E\u305F\u306F\u8907\u6570\u306E\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u30B9\u30BF\u30FC\u30C8\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30B8\u30E7\u30D6\u306F\u30AD\u30E3\u30F3\u30BB\u30EB\u3055\u308C\u307E\u3057\u305F\u3002 -IngestManager.StartIngestJobsTask.run.startupErr.dlgSolution=\u5931\u6557\u3057\u305F\u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u7121\u52B9\u5316\u3059\u308B\u304B\u30A8\u30E9\u30FC\u3092\u89E3\u6C7A\u3057\u3001\u305D\u306E\u5F8C\u30C7\u30FC\u30BF\u30BD\u30FC\u30B9\u3092\u53F3\u30AF\u30EA\u30C3\u30AF\u3057\u3001\n\u300C\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u5B9F\u884C\u300D\u3092\u9078\u629E\u3057\u3066\u3001\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u3092\u518D\u5B9F\u884C\u3057\u3066\u4E0B\u3055\u3044\u3002 -IngestManager.StartIngestJobsTask.run.startupErr.dlgTitle=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u5931\u6557 -IngestJobSettings.createModuleSettingsFolder.warning=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u8A2D\u5B9A\u30D5\u30A9\u30EB\u30C0\u306E\u4F5C\u6210\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002\u8A2D\u5B9A\u3092\u4FDD\u5B58\u3067\u304D\u307E\u305B\u3093\u3002 -IngestJob.progress.dataSourceIngest.initialDisplayName={0}\u3092\u89E3\u6790\u4E2D -IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.dataSource=\u30C7\u30FC\u30BF\u30BD\u30FC\u30B9 -IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.elapsedTime=\u7D4C\u904E\u6642\u9593\uFF08\u6642\uFF1A\u5206\uFF1A\u79D2\uFF09 -IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.file=\u30D5\u30A1\u30A4\u30EB -IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.startTime=\u958B\u59CB\u6642\u9593 -IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.threadID=\u30B9\u30EC\u30C3\u30C9ID -IngestManager.IngestMessage.ErrorMessageLimitReached.msg=\u6700\u5927\u6570({0})\u306E\u30A8\u30E9\u30FC\u304A\u3088\u3073\u307E\u305F\u306F\u8B66\u544A\u30E1\u30C3\u30BB\u30FC\u30B8\u304C\u63B2\u8F09\u3055\u308C\u307E\u3057\u305F\u3002\u3055\u3089\u306A\u308B\u30A8\u30E9\u30FC\uFF0F\u8B66\u544A\u306F\u30ED\u30B0\u3092\u78BA\u8A8D\u3057\u3066\u4E0B\u3055\u3044\uFF08\u30D8\u30EB\u30D7->\u30ED\u30B0\u30D5\u30A9\u30EB\u30C0\u30FC\u3092\u958B\u304F\uFF09 -IngestManager.IngestMessage.ErrorMessageLimitReached.subject=\u6700\u5927\u6570\u306E\u30A8\u30E9\u30FC\u304C\u63B2\u8F09\u3055\u308C\u307E\u3057\u305F -IngestManager.IngestMessage.ErrorMessageLimitReached.title=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30DE\u30CD\u30B8\u30E3\u30FC -IngestManager.IngestThreadActivitySnapshot.idleThread=\u30A2\u30A4\u30C9\u30EB -IngestProgressSnapshotDialog.title.text=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30D7\u30ED\u30B0\u30EC\u30B9\u30FB\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8 -IngestProgressSnapshotPanel.closeButton.text=\u9589\u3058\u308B -IngestProgressSnapshotPanel.refreshButton.text=\u30EA\u30D5\u30EC\u30C3\u30B7\u30E5 -IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.activity=\u30A2\u30AF\u30C6\u30A3\u30D3\u30C6\u30A3 -IngestJobSettingsPanel.advancedButton.actionCommand=\u30A2\u30C9\u30D0\u30F3\u30B9 -IngestJobSettingsPanel.advancedButton.text=\u30A2\u30C9\u30D0\u30F3\u30B9 +IngestMessageTopComponent.initComponents.name=\u30a4\u30f3\u30dc\u30c3\u30af\u30b9\u3092\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8 +IngestMessageTopComponent.msgDlg.ingestRpt.text=\u30ec\u30dd\u30fc\u30c8\u3092\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8 +IngestMonitor.mgrErrMsg.lowDiskSpace.msg=\u30c7\u30a3\u30b9\u30af{0}\u306e\u30c7\u30a3\u30b9\u30af\u9818\u57df\u4e0d\u8db3\u306e\u305f\u3081\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3092\u4e2d\u6b62\u3057\u307e\u3059\u3002\n\u30b1\u30fc\u30b9\u30c9\u30e9\u30a4\u30d6\u306b\u6700\u4f4e1GB\u306e\u7a7a\u304d\u9818\u57df\u304c\u3042\u308b\u306e\u3092\u78ba\u8a8d\u3057\u3001\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3092\u518d\u5b9f\u884c\u3057\u3066\u4e0b\u3055\u3044\u3002 +IngestMonitor.mgrErrMsg.lowDiskSpace.title=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u304c\u4e2d\u6b62\u3055\u308c\u307e\u3057\u305f\u30fc{0}\u306e\u30c7\u30a3\u30b9\u30af\u9818\u57df\u4e0d\u8db3 +OpenIDE-Module-Name=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8 +IngestManager.StartIngestJobsTask.run.startupErr.dlgErrorList=\n\u30a8\u30e9\u30fc\uff1a\n{0} +IngestManager.StartIngestJobsTask.run.startupErr.dlgMsg=\u5358\u6570\u307e\u305f\u306f\u8907\u6570\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u30b9\u30bf\u30fc\u30c8\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b8\u30e7\u30d6\u306f\u30ad\u30e3\u30f3\u30bb\u30eb\u3055\u308c\u307e\u3057\u305f\u3002 +IngestManager.StartIngestJobsTask.run.startupErr.dlgSolution=\u5931\u6557\u3057\u305f\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u7121\u52b9\u5316\u3059\u308b\u304b\u30a8\u30e9\u30fc\u3092\u89e3\u6c7a\u3057\u3001\u305d\u306e\u5f8c\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u53f3\u30af\u30ea\u30c3\u30af\u3057\u3001\n\u300c\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u5b9f\u884c\u300d\u3092\u9078\u629e\u3057\u3066\u3001\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3092\u518d\u5b9f\u884c\u3057\u3066\u4e0b\u3055\u3044\u3002 +IngestManager.StartIngestJobsTask.run.startupErr.dlgTitle=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u5931\u6557 +IngestJobSettings.createModuleSettingsFolder.warning=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u8a2d\u5b9a\u30d5\u30a9\u30eb\u30c0\u306e\u4f5c\u6210\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002\u8a2d\u5b9a\u3092\u4fdd\u5b58\u3067\u304d\u307e\u305b\u3093\u3002 +IngestJob.progress.dataSourceIngest.initialDisplayName={0}\u3092\u89e3\u6790\u4e2d +IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.dataSource=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9 +IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.elapsedTime=\u7d4c\u904e\u6642\u9593\uff08\u6642\uff1a\u5206\uff1a\u79d2\uff09 +IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.file=\u30d5\u30a1\u30a4\u30eb +IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.startTime=\u958b\u59cb\u6642\u9593 +IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.threadID=\u30b9\u30ec\u30c3\u30c9ID +IngestManager.IngestMessage.ErrorMessageLimitReached.msg=\u6700\u5927\u6570({0})\u306e\u30a8\u30e9\u30fc\u304a\u3088\u3073\u307e\u305f\u306f\u8b66\u544a\u30e1\u30c3\u30bb\u30fc\u30b8\u304c\u63b2\u8f09\u3055\u308c\u307e\u3057\u305f\u3002\u3055\u3089\u306a\u308b\u30a8\u30e9\u30fc\uff0f\u8b66\u544a\u306f\u30ed\u30b0\u3092\u78ba\u8a8d\u3057\u3066\u4e0b\u3055\u3044\uff08\u30d8\u30eb\u30d7->\u30ed\u30b0\u30d5\u30a9\u30eb\u30c0\u30fc\u3092\u958b\u304f\uff09 +IngestManager.IngestMessage.ErrorMessageLimitReached.subject=\u6700\u5927\u6570\u306e\u30a8\u30e9\u30fc\u304c\u63b2\u8f09\u3055\u308c\u307e\u3057\u305f +IngestManager.IngestMessage.ErrorMessageLimitReached.title=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30de\u30cd\u30b8\u30e3\u30fc +IngestManager.IngestThreadActivitySnapshot.idleThread=\u30a2\u30a4\u30c9\u30eb +IngestProgressSnapshotDialog.title.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30d7\u30ed\u30b0\u30ec\u30b9\u30fb\u30b9\u30ca\u30c3\u30d7\u30b7\u30e7\u30c3\u30c8 +IngestProgressSnapshotPanel.closeButton.text=\u9589\u3058\u308b +IngestProgressSnapshotPanel.refreshButton.text=\u30ea\u30d5\u30ec\u30c3\u30b7\u30e5 +IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.activity=\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3 +IngestJobSettingsPanel.advancedButton.actionCommand=\u30a2\u30c9\u30d0\u30f3\u30b9 +IngestJobSettingsPanel.advancedButton.text=\u30a2\u30c9\u30d0\u30f3\u30b9 ModuleTableModel.colName.duration=\u6240\u8981\u6642\u9593 -IngestJob.cancellationDialog.title=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u3092\u30AD\u30E3\u30F3\u30BB\u30EB -IngestJobSettings.missingModule.warning=\u4EE5\u524D\u306B\u8AAD\u307F\u8FBC\u3093\u3060{0}\u30E2\u30B8\u30E5\u30FC\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002 -DataSourceIngestCancellationPanel.cancelAllModulesRadioButton.text=\u5168\u3066\u306E\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u30AD\u30E3\u30F3\u30BB\u30EB -DataSourceIngestCancellationPanel.cancelCurrentModuleRadioButton.text=\u73FE\u5728\u306E\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u307F\u30AD\u30E3\u30F3\u30BB\u30EB -FileIngestCancellationPanel.cancelFileIngestRadioButton.text=\u30D5\u30A1\u30A4\u30EB\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u306E\u307F\u30AD\u30E3\u30F3\u30BB\u30EB -FileIngestCancellationPanel.cancelIngestJobRadioButton.text=\u30C7\u30FC\u30BF\u30BD\u30FC\u30B9\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u304A\u3088\u3073\u30D5\u30A1\u30A4\u30EB\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u3092\u30AD\u30E3\u30F3\u30BB\u30EB -IngestJobSettings.moduleSettingsLoad.warning={1}\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\u306E{0}\u30E2\u30B8\u30E5\u30FC\u30EB\u7528\u306E\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30B8\u30E7\u30D6\u8A2D\u5B9A\u3092\u8AAD\u307F\u8FBC\u307F\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002\u30C7\u30D5\u30A9\u30EB\u30C8\u8A2D\u5B9A\u3092\u4F7F\u7528\u3057\u3066\u3044\u307E\u3059\u3002 -IngestJobSettings.save.warning={0}\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30B8\u30E7\u30D6\u8A2D\u5B9A\u3092\u4FDD\u5B58\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002 -IngestJobTableModel.colName.dataSource=\u30C7\u30FC\u30BF\u30BD\u30FC\u30B9 -IngestJobTableModel.colName.dirQueued=\u30AD\u30E5\u30FC\u3055\u308C\u305F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA -IngestJobTableModel.colName.filesPerSec=\u30D5\u30A1\u30A4\u30EB\uFF0F\u79D2 -IngestJobTableModel.colName.filesQueued=\u30AD\u30E5\u30FC\u3055\u308C\u305F\u30D5\u30A1\u30A4\u30EB -IngestJobTableModel.colName.inProgress=\u51E6\u7406\u4E2D -IngestJobTableModel.colName.jobID=\u30B8\u30E7\u30D6ID -IngestJobTableModel.colName.numProcessed=\u51E6\u7406\u3055\u308C\u305F\u6570 -IngestJobTableModel.colName.rootQueued=\u30AD\u30E5\u30FC\u3055\u308C\u305F\u30EB\u30FC\u30C8 -IngestJobTableModel.colName.start=\u30B9\u30BF\u30FC\u30C8 -IngestModuleFactoryLoader.errorMessages.duplicateDisplayName=\u5225\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u540D\u524D\u3092\u91CD\u8907\u3059\u308B\u3001{0}\u306E\u540D\u524D\u3092\u6301\u3064\u30E2\u30B8\u30E5\u30FC\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u3057\u305F\u3002\u30E2\u30B8\u30E5\u30FC\u30EB\u306F\u4F7F\u7528\u3057\u307E\u305B\u3093\u3002 -IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.jobID=\u30B8\u30E7\u30D6ID -ModuleTableModel.colName.module=\u30E2\u30B8\u30E5\u30FC\u30EB -IngestJobSettingsPanel.processUnallocCheckbox.toolTipText=\u524A\u9664\u3055\u308C\u305F\u30D5\u30A1\u30A4\u30EB\u7B49\u306E\u672A\u5272\u308A\u5F53\u3066\u9818\u57DF\u3092\u51E6\u7406\u3002\u3088\u308A\u5B8C\u5168\u306A\u7D50\u679C\u304C\u51FA\u307E\u3059\u304C\u3001\u5927\u304D\u3044\u30A4\u30E1\u30FC\u30B8\u3067\u306F\u51E6\u7406\u6642\u9593\u304C\u9577\u304F\u306A\u308B\u304B\u3082\u3057\u308C\u307E\u305B\u3093\u3002 +IngestJob.cancellationDialog.title=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3092\u30ad\u30e3\u30f3\u30bb\u30eb +IngestJobSettings.missingModule.warning=\u4ee5\u524d\u306b\u8aad\u307f\u8fbc\u3093\u3060{0}\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +DataSourceIngestCancellationPanel.cancelAllModulesRadioButton.text=\u5168\u3066\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u30ad\u30e3\u30f3\u30bb\u30eb +DataSourceIngestCancellationPanel.cancelCurrentModuleRadioButton.text=\u73fe\u5728\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u307f\u30ad\u30e3\u30f3\u30bb\u30eb +FileIngestCancellationPanel.cancelFileIngestRadioButton.text=\u30d5\u30a1\u30a4\u30eb\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u306e\u307f\u30ad\u30e3\u30f3\u30bb\u30eb +FileIngestCancellationPanel.cancelIngestJobRadioButton.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u304a\u3088\u3073\u30d5\u30a1\u30a4\u30eb\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3092\u30ad\u30e3\u30f3\u30bb\u30eb +IngestJobSettings.moduleSettingsLoad.warning={1}\u30b3\u30f3\u30c6\u30ad\u30b9\u30c8\u306e{0}\u30e2\u30b8\u30e5\u30fc\u30eb\u7528\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b8\u30e7\u30d6\u8a2d\u5b9a\u3092\u8aad\u307f\u8fbc\u307f\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002\u30c7\u30d5\u30a9\u30eb\u30c8\u8a2d\u5b9a\u3092\u4f7f\u7528\u3057\u3066\u3044\u307e\u3059\u3002 +IngestJobSettings.save.warning={0}\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b8\u30e7\u30d6\u8a2d\u5b9a\u3092\u4fdd\u5b58\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +IngestJobTableModel.colName.dataSource=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9 +IngestJobTableModel.colName.dirQueued=\u30ad\u30e5\u30fc\u3055\u308c\u305f\u30c7\u30a3\u30ec\u30af\u30c8\u30ea +IngestJobTableModel.colName.filesPerSec=\u30d5\u30a1\u30a4\u30eb\uff0f\u79d2 +IngestJobTableModel.colName.filesQueued=\u30ad\u30e5\u30fc\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb +IngestJobTableModel.colName.inProgress=\u51e6\u7406\u4e2d +IngestJobTableModel.colName.jobID=\u30b8\u30e7\u30d6ID +IngestJobTableModel.colName.numProcessed=\u51e6\u7406\u3055\u308c\u305f\u6570 +IngestJobTableModel.colName.rootQueued=\u30ad\u30e5\u30fc\u3055\u308c\u305f\u30eb\u30fc\u30c8 +IngestJobTableModel.colName.start=\u30b9\u30bf\u30fc\u30c8 +IngestModuleFactoryLoader.errorMessages.duplicateDisplayName=\u5225\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u540d\u524d\u3092\u91cd\u8907\u3059\u308b\u3001{0}\u306e\u540d\u524d\u3092\u6301\u3064\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u898b\u3064\u304b\u308a\u307e\u3057\u305f\u3002\u30e2\u30b8\u30e5\u30fc\u30eb\u306f\u4f7f\u7528\u3057\u307e\u305b\u3093\u3002 +IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.jobID=\u30b8\u30e7\u30d6ID +ModuleTableModel.colName.module=\u30e2\u30b8\u30e5\u30fc\u30eb +IngestJobSettingsPanel.processUnallocCheckbox.toolTipText=\u524a\u9664\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb\u7b49\u306e\u672a\u5272\u308a\u5f53\u3066\u9818\u57df\u3092\u51e6\u7406\u3002\u3088\u308a\u5b8c\u5168\u306a\u7d50\u679c\u304c\u51fa\u307e\u3059\u304c\u3001\u5927\u304d\u3044\u30a4\u30e1\u30fc\u30b8\u3067\u306f\u51e6\u7406\u6642\u9593\u304c\u9577\u304f\u306a\u308b\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002 -IngestJobSettingsPanel.processUnallocCheckbox.text=\u672A\u5272\u308A\u5F53\u3066\u9818\u57DF\u306E\u51E6\u7406 -Menu/Tools/RunIngestModules=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u5B9F\u884C -IngestJob.progress.fileIngest.cancelMessage={1}\u306E{0}\u3092\u5F85\u3063\u3066\u3044\u307E\u3059 -IngestManager.OpenEventChannel.Fail.ErrMsg=\u3053\u306E\u30B1\u30FC\u30B9\u3067\u4F7F\u308F\u308C\u3066\u3044\u308B\u304B\u3082\u3057\u308C\u306A\u3044\u4ED6\u306E\u30CE\u30FC\u30C9\u306B\u89E3\u6790\u30D7\u30ED\u30BB\u30B9\u304C\u63A5\u7D9A\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002 -IngestManager.OpenEventChannel.Fail.Title=\u63A5\u7D9A\u5931\u6557 -IngestJobSettings.moduleSettingsSave.warning={1}\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\u306E{0}\u30E2\u30B8\u30E5\u30FC\u30EB\u7528\u306E\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30B8\u30E7\u30D6\u8A2D\u5B9A\u3092\u8AAD\u307F\u8FBC\u307F\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002 -IngestJobTableModel.colName.dsQueued=\u30AD\u30E5\u30FC\u3055\u308C\u305FDS -IngestJobSettingsPanel.jButtonSelectAll.text=\u5168\u3066\u9078\u629E -IngestJobSettingsPanel.jButtonDeselectAll.text=\u5168\u3066\u9078\u629E\u89E3\u9664 -IngestManager.cancellingIngest.msgDlg.text=\u73FE\u5728\u5B9F\u884C\u4E2D\u306E\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30B8\u30E7\u30D6\u3092\u30AD\u30E3\u30F3\u30BB\u30EB\u4E2D -IngestManager.serviceIsDown.msgDlg.text={0}\u304C\u30C0\u30A6\u30F3\u3057\u3066\u3044\u307E\u3059 -RunIngestSubMenu.menuItem.empty=\u30FC\u7A7A\u767D\u30FC -RunIngestModulesMenu.getName.text=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u5B9F\u884C -DataSourceIngestPipeline.moduleError.title.text={0}\u30A8\u30E9\u30FC -FileIngestPipeline.moduleError.title.text={0}\u30A8\u30E9\u30FC -IngestJob.cancelReason.notCancelled.text=\u30AD\u30E3\u30F3\u30BB\u30EB\u3055\u308C\u3066\u3044\u307E\u305B\u3093 -IngestJob.cancelReason.cancelledByUser.text=\u30E6\u30FC\u30B6\u30FC\u304C\u30AD\u30E3\u30F3\u30BB\u30EB\u3057\u307E\u3057\u305F -IngestJob.cancelReason.ingestModStartFail.text=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u8D77\u52D5\u306B\u5931\u6557 -IngestJob.cancelReason.outOfDiskSpace.text=\u30C7\u30A3\u30B9\u30AF\u30B9\u30DA\u30FC\u30B9\u304C\u8DB3\u308A\u307E\u305B\u3093 -IngestJob.cancelReason.servicesDown.text=\u30AD\u30E3\u30F3\u30BB\u30EB\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F -IngestJob.cancelReason.caseClosed.text=\u30B1\u30FC\u30B9\u3092\u9589\u3058\u307E\u3057\u305F +IngestJobSettingsPanel.processUnallocCheckbox.text=\u672a\u5272\u308a\u5f53\u3066\u9818\u57df\u306e\u51e6\u7406 +Menu/Tools/RunIngestModules=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u5b9f\u884c +IngestJob.progress.fileIngest.cancelMessage={1}\u306e{0}\u3092\u5f85\u3063\u3066\u3044\u307e\u3059 +IngestManager.OpenEventChannel.Fail.ErrMsg=\u3053\u306e\u30b1\u30fc\u30b9\u3067\u4f7f\u308f\u308c\u3066\u3044\u308b\u304b\u3082\u3057\u308c\u306a\u3044\u4ed6\u306e\u30ce\u30fc\u30c9\u306b\u89e3\u6790\u30d7\u30ed\u30bb\u30b9\u304c\u63a5\u7d9a\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +IngestManager.OpenEventChannel.Fail.Title=\u63a5\u7d9a\u5931\u6557 +IngestJobSettings.moduleSettingsSave.warning={1}\u30b3\u30f3\u30c6\u30ad\u30b9\u30c8\u306e{0}\u30e2\u30b8\u30e5\u30fc\u30eb\u7528\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b8\u30e7\u30d6\u8a2d\u5b9a\u3092\u8aad\u307f\u8fbc\u307f\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +IngestJobTableModel.colName.dsQueued=\u30ad\u30e5\u30fc\u3055\u308c\u305fDS +IngestJobSettingsPanel.jButtonSelectAll.text=\u5168\u3066\u9078\u629e +IngestJobSettingsPanel.jButtonDeselectAll.text=\u5168\u3066\u9078\u629e\u89e3\u9664 +IngestManager.cancellingIngest.msgDlg.text=\u73fe\u5728\u5b9f\u884c\u4e2d\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b8\u30e7\u30d6\u3092\u30ad\u30e3\u30f3\u30bb\u30eb\u4e2d +IngestManager.serviceIsDown.msgDlg.text={0}\u304c\u30c0\u30a6\u30f3\u3057\u3066\u3044\u307e\u3059 +RunIngestSubMenu.menuItem.empty=\u30fc\u7a7a\u767d\u30fc +RunIngestModulesMenu.getName.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u5b9f\u884c +DataSourceIngestPipeline.moduleError.title.text={0}\u30a8\u30e9\u30fc +FileIngestPipeline.moduleError.title.text={0}\u30a8\u30e9\u30fc +IngestJob.cancelReason.notCancelled.text=\u30ad\u30e3\u30f3\u30bb\u30eb\u3055\u308c\u3066\u3044\u307e\u305b\u3093 +IngestJob.cancelReason.cancelledByUser.text=\u30e6\u30fc\u30b6\u30fc\u304c\u30ad\u30e3\u30f3\u30bb\u30eb\u3057\u307e\u3057\u305f +IngestJob.cancelReason.ingestModStartFail.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u8d77\u52d5\u306b\u5931\u6557 +IngestJob.cancelReason.outOfDiskSpace.text=\u30c7\u30a3\u30b9\u30af\u30b9\u30da\u30fc\u30b9\u304c\u8db3\u308a\u307e\u305b\u3093 +IngestJob.cancelReason.caseClosed.text=\u30b1\u30fc\u30b9\u3092\u9589\u3058\u307e\u3057\u305f diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettings.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettings.java index de15f82949..827bbc016d 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettings.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettings.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2014 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -39,8 +39,10 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.python.util.PythonObjectInputStream; /** - * Encapsulates the ingest job settings for a particular context such as the Add - * Data Source wizard or the Run Ingest Modules dialog. + * Encapsulates the ingest job settings for a particular execution context. + * Examples of execution contexts include the add data source wizard and the run + * ingest modules dialog. Different execution conterxts may have different + * ingest job settings. */ public class IngestJobSettings { @@ -60,19 +62,30 @@ public class IngestJobSettings { private boolean processUnallocatedSpace; private final List warnings; - // Determines which modeules to run + /** + * The type of ingest modules to run. + */ public enum IngestType { - // Run all modules + /** + * Run both data source level and file-level ingest modules. + */ ALL_MODULES, - // Run only data source modules + /** + * Run only data source level ingest modules. + */ DATA_SOURCE_ONLY, - // Run only files modules + /** + * Run only file level ingest modules. + */ FILES_ONLY } /** - * Constructs an ingest job settings object for a given context. + * Constructs an ingest job settings object for a given execution context. + * Examples of execution contexts include the add data source wizard and the + * run ingest modules dialog. Different execution conterxts may have + * different ingest job settings. * * @param executionContext The ingest execution context identifier. */ @@ -87,7 +100,10 @@ public class IngestJobSettings { } /** - * Constructs an ingest job settings object for a given context. + * Constructs an ingest job settings object for a given context. Examples of + * execution contexts include the add data source wizard and the run ingest + * modules dialog. Different execution conterxts may have different ingest + * job settings. * * @param context The context identifier string. * @param ingestType The type of modules ingest is running. @@ -116,9 +132,12 @@ public class IngestJobSettings { } /** - * Get the ingest execution context identifier. + * Gets the ingest execution context identifier. Examples of execution + * contexts include the add data source wizard and the run ingest modules + * dialog. Different execution conterxts may have different ingest job + * settings. * - * @return The context string. + * @return The execution context identifier. */ String getExecutionContext() { return this.executionContext; diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java index f528cba6e6..c196caba8a 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java @@ -71,28 +71,27 @@ public class IngestManager { private static IngestManager instance; private final Object ingestMessageBoxLock = new Object(); - /** - * The ingest manager maintains a mapping of ingest job IDs to running + /* + * The ingest manager maintains a mapping of ingest job ids to running * ingest jobs. */ - private final ConcurrentHashMap jobsById; + private final Map jobsById; - /** + /* * Each runnable/callable task the ingest manager submits to its thread * pools is given a unique thread/task ID. */ private final AtomicLong nextThreadId; - /** - * Ingest jobs may be queued to be started on a pool thread by ingest job - * starters. A mapping of thread/task IDs to the result objects associated - * with each ingest job starter is maintained to provide handles that can be - * used to cancel the ingest job starter. + /* + * Ingest jobs may be queued to be started on a pool thread by start ingest + * job tasks. A mapping of task ids to the Future objects for each task is + * maintained to allow for task cancellation. */ - private final ConcurrentHashMap> ingestJobStarters; + private final Map> startIngestJobTasks; private final ExecutorService startIngestJobsThreadPool; - /** + /* * Ingest jobs use an ingest task scheduler to break themselves down into * data source level and file level tasks. The ingest scheduler puts these * ingest tasks into queues for execution on ingest manager pool threads by @@ -118,14 +117,14 @@ public class IngestManager { private AutopsyEventPublisher moduleEventPublisher; private final ExecutorService eventPublishingExecutor; - /** + /* * The ingest manager uses an ingest monitor to determine when system * resources are under pressure. If the monitor detects such a situation, it * calls back to the ingest manager to cancel all ingest jobs in progress. */ private final IngestMonitor ingestMonitor; - /** + /* * The ingest manager provides access to a top component that is used by * ingest module to post messages for the user. A count of the posts is used * as a cap to avoid bogging down the application. @@ -134,7 +133,7 @@ public class IngestManager { private volatile IngestMessageTopComponent ingestMessageBox; private final AtomicLong ingestErrorMessagePosts; - /** + /* * The ingest manager supports reporting of ingest processing progress by * collecting snapshots of the activities of the ingest threads, ingest job * progress, and ingest module run times. @@ -142,13 +141,13 @@ public class IngestManager { private final ConcurrentHashMap ingestThreadActivitySnapshots; private final ConcurrentHashMap ingestModuleRunTimes; - /** + /* * The ingest job creation capability of the ingest manager can be turned on * and off to support an orderly shut down of the application. */ private volatile boolean jobCreationIsEnabled; - /** + /* * Ingest manager subscribes to service outage notifications. If key * services are down, ingest manager cancels all ingest jobs in progress. */ @@ -264,8 +263,8 @@ public class IngestManager { this.dataSourceIngestThreadPool = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat("IM-data-source-ingest-%d").build()); //NON-NLS this.startIngestJobsThreadPool = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat("IM-start-ingest-jobs-%d").build()); //NON-NLS this.nextThreadId = new AtomicLong(0L); - this.jobsById = new ConcurrentHashMap<>(); - this.ingestJobStarters = new ConcurrentHashMap<>(); + this.jobsById = new HashMap<>(); + this.startIngestJobTasks = new ConcurrentHashMap<>(); this.servicesMonitor = ServicesMonitor.getInstance(); subscribeToServiceMonitorEvents(); @@ -329,7 +328,7 @@ public class IngestManager { public void propertyChange(PropertyChangeEvent evt) { if (evt.getNewValue().equals(ServicesMonitor.ServiceStatus.DOWN.toString())) { - // check whether a milti-user case is currently being processed + // check whether a multi-user case is currently being processed try { if (!Case.isCaseOpen() || Case.getCurrentCase().getCaseType() != Case.CaseType.MULTI_USER_CASE) { return; @@ -474,13 +473,13 @@ public class IngestManager { * @param dataSources The data sources to process. * @param settings The settings for the ingest job. */ - public synchronized void queueIngestJob(Collection dataSources, IngestJobSettings settings) { - if (this.jobCreationIsEnabled) { + public void queueIngestJob(Collection dataSources, IngestJobSettings settings) { + if (jobCreationIsEnabled) { IngestJob job = new IngestJob(dataSources, settings, RuntimeProperties.coreComponentsAreActive()); if (job.hasIngestPipeline()) { long taskId = nextThreadId.incrementAndGet(); Future task = startIngestJobsThreadPool.submit(new StartIngestJobTask(taskId, job)); - ingestJobStarters.put(taskId, task); + startIngestJobTasks.put(taskId, task); } } } @@ -544,20 +543,18 @@ public class IngestManager { ingestMonitor.start(); } - /** - * Add the job to the jobs map now so that isIngestRunning() will - * return true while the modules read global settings during start - * up. This works because the core global settings panels restrict - * changes while analysis is in progress. - */ - this.jobsById.put(job.getId(), job); + synchronized (jobsById) { + jobsById.put(job.getId(), job); + } List errors = job.start(); if (errors.isEmpty()) { this.fireIngestJobStarted(job.getId()); IngestManager.logger.log(Level.INFO, "Ingest job {0} started", job.getId()); //NON-NLS success = true; } else { - this.jobsById.remove(job.getId()); + synchronized (jobsById) { + this.jobsById.remove(job.getId()); + } for (IngestModuleError error : errors) { logger.log(Level.SEVERE, String.format("Error starting %s ingest module", error.getModuleDisplayName()), error.getModuleError()); //NON-NLS } @@ -599,13 +596,15 @@ public class IngestManager { synchronized void finishIngestJob(IngestJob job) { long jobId = job.getId(); - this.jobsById.remove(jobId); + synchronized (jobsById) { + jobsById.remove(jobId); + } if (!job.isCancelled()) { IngestManager.logger.log(Level.INFO, "Ingest job {0} completed", jobId); //NON-NLS - this.fireIngestJobCompleted(jobId); + fireIngestJobCompleted(jobId); } else { IngestManager.logger.log(Level.INFO, "Ingest job {0} cancelled", jobId); //NON-NLS - this.fireIngestJobCancelled(jobId); + fireIngestJobCancelled(jobId); } } @@ -615,7 +614,9 @@ public class IngestManager { * @return True or false. */ public boolean isIngestRunning() { - return !this.jobsById.isEmpty(); + synchronized (jobsById) { + return !jobsById.isEmpty(); + } } /** @@ -625,7 +626,7 @@ public class IngestManager { * instead. */ @Deprecated - public synchronized void cancelAllIngestJobs() { + public void cancelAllIngestJobs() { cancelAllIngestJobs(IngestJob.CancellationReason.USER_CANCELLED); } @@ -634,15 +635,21 @@ public class IngestManager { * * @param reason The cancellation reason. */ - public synchronized void cancelAllIngestJobs(IngestJob.CancellationReason reason) { - // Stop creating new ingest jobs. - for (Future handle : ingestJobStarters.values()) { + public void cancelAllIngestJobs(IngestJob.CancellationReason reason) { + /* + * Cancel the start job tasks. + */ + for (Future handle : startIngestJobTasks.values()) { handle.cancel(true); } - // Cancel all the jobs already created. - for (IngestJob job : this.jobsById.values()) { - job.cancel(reason); + /* + * Cancel the jobs in progress. + */ + synchronized (jobsById) { + for (IngestJob job : this.jobsById.values()) { + job.cancel(reason); + } } } @@ -903,8 +910,10 @@ public class IngestManager { */ List getIngestJobSnapshots() { List snapShots = new ArrayList<>(); - for (IngestJob job : this.jobsById.values()) { - snapShots.addAll(job.getDataSourceIngestJobSnapshots()); + synchronized (jobsById) { + for (IngestJob job : jobsById.values()) { + snapShots.addAll(job.getDataSourceIngestJobSnapshots()); + } } return snapShots; } @@ -941,7 +950,9 @@ public class IngestManager { public Void call() { try { if (Thread.currentThread().isInterrupted()) { - jobsById.remove(job.getId()); + synchronized (jobsById) { + jobsById.remove(job.getId()); + } return null; } @@ -953,7 +964,7 @@ public class IngestManager { if (progress != null) { progress.setDisplayName(NbBundle.getMessage(this.getClass(), "IngestManager.StartIngestJobsTask.run.cancelling", displayName)); } - Future handle = ingestJobStarters.remove(threadId); + Future handle = startIngestJobTasks.remove(threadId); handle.cancel(true); return true; } @@ -968,7 +979,7 @@ public class IngestManager { if (null != progress) { progress.finish(); } - ingestJobStarters.remove(threadId); + startIngestJobTasks.remove(threadId); } } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/RunIngestModulesDialog.java b/Core/src/org/sleuthkit/autopsy/ingest/RunIngestModulesDialog.java index 27b7f3ecf5..26f4fd6a11 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/RunIngestModulesDialog.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/RunIngestModulesDialog.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013-2015 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -39,11 +39,14 @@ import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Directory; /** - * Dialog box that allows a user to configure and run an ingest job on one or - * more data sources. + * + * A dialog box that allows a user to configure and execute analysis of one or + * more data sources with ingest modules or analysis of the contents of a + * directory with file-level ingest modules. */ public final class RunIngestModulesDialog extends JDialog { + private static final long serialVersionUID = 1L; private static final String TITLE = NbBundle.getMessage(RunIngestModulesDialog.class, "IngestDialog.title.text"); private final IngestType ingestType; private static Dimension DIMENSIONS = new Dimension(500, 300); @@ -51,13 +54,13 @@ public final class RunIngestModulesDialog extends JDialog { private IngestJobSettingsPanel ingestJobSettingsPanel; /** - * Construct a dialog box that allows a user to configure and run an ingest - * job on one or more data sources. + * Constructs a dialog box that allows a user to configure and execute + * analysis of one or more data sources with ingest modules. * * @param frame The dialog parent window. * @param title The title for the dialog. * @param modal True if the dialog should be modal, false otherwise. - * @param dataSources The data sources to be processed. + * @param dataSources The data sources to be analyzed. */ public RunIngestModulesDialog(JFrame frame, String title, boolean modal, List dataSources) { super(frame, title, modal); @@ -66,60 +69,26 @@ public final class RunIngestModulesDialog extends JDialog { } /** - * Construct a dialog box that allows a user to configure and run an ingest - * job on one or more data sources. + * Constructs a dialog box that allows a user to configure and execute + * analysis of one or more data sources with ingest modules. * * @param dataSources The data sources to be processed. */ public RunIngestModulesDialog(List dataSources) { this(new JFrame(TITLE), TITLE, true, dataSources); } - + + /** + * Constructs a dialog box that allows a user to configure and execute + * analysis of the contents of a directory with file-level ingest modules. + * + * @param dir + */ public RunIngestModulesDialog(Directory dir) { this.dataSources.add(dir); this.ingestType = IngestType.FILES_ONLY; } - /** - * Construct a dialog box that allows a user to configure and run an ingest - * job on one or more data sources. - * - * @param frame The dialog parent window. - * @param title The title for the dialog. - * @param modal True if the dialog should be modal, false otherwise. - * - * @deprecated - */ - @Deprecated - public RunIngestModulesDialog(JFrame frame, String title, boolean modal) { - super(frame, title, modal); - this.ingestType = IngestType.ALL_MODULES; - } - - /** - * Construct a dialog box that allows a user to configure and run an ingest - * job on one or more data sources. - * - * @deprecated - */ - @Deprecated - public RunIngestModulesDialog() { - this(new JFrame(TITLE), TITLE, true); - } - - /** - * Set the data sources to be processed. - * - * @param dataSources The data sources. - * - * @deprecated - */ - @Deprecated - public void setDataSources(List dataSources) { - this.dataSources.clear(); - this.dataSources.addAll(dataSources); - } - /** * Displays this dialog. */ @@ -139,7 +108,7 @@ public final class RunIngestModulesDialog extends JDialog { * Get the default or saved ingest job settings for this context and use * them to create and add an ingest job settings panel. */ - IngestJobSettings ingestJobSettings = new IngestJobSettings(RunIngestModulesDialog.class.getCanonicalName(), this.ingestType); + IngestJobSettings ingestJobSettings = new IngestJobSettings(RunIngestModulesDialog.class.getCanonicalName(), this.ingestType); RunIngestModulesDialog.showWarnings(ingestJobSettings); this.ingestJobSettingsPanel = new IngestJobSettingsPanel(ingestJobSettings); add(this.ingestJobSettingsPanel, BorderLayout.PAGE_START); @@ -227,4 +196,45 @@ public final class RunIngestModulesDialog extends JDialog { JOptionPane.showMessageDialog(null, warningMessage.toString()); } } + + /** + * Constructs a dialog box that allows a user to configure and execute + * analysis of one or more data sources with ingest modules. + * + * @param frame The dialog parent window. + * @param title The title for the dialog. + * @param modal True if the dialog should be modal, false otherwise. + * + * @deprecated + */ + @Deprecated + public RunIngestModulesDialog(JFrame frame, String title, boolean modal) { + super(frame, title, modal); + this.ingestType = IngestType.ALL_MODULES; + } + + /** + * Constructs a dialog box that allows a user to configure and run an ingest + * job on one or more data sources. + * + * @deprecated + */ + @Deprecated + public RunIngestModulesDialog() { + this(new JFrame(TITLE), TITLE, true); + } + + /** + * Sets the data sources to be processed. + * + * @param dataSources The data sources. + * + * @deprecated + */ + @Deprecated + public void setDataSources(List dataSources) { + this.dataSources.clear(); + this.dataSources.addAll(dataSources); + } + } diff --git a/Core/src/org/sleuthkit/autopsy/modules/UserArtifacts/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/UserArtifacts/Bundle.properties deleted file mode 100755 index fb927c8e40..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/UserArtifacts/Bundle.properties +++ /dev/null @@ -1,2 +0,0 @@ -UserArtifactIngestModuleFactory.moduleName=Custom Artifact Adder -UserArtifactIngestModuleFactory.moduleDescription=Adds custom artifact types \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/modules/UserArtifacts/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/modules/UserArtifacts/Bundle_ja.properties deleted file mode 100644 index 990fd0aa8c..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/UserArtifacts/Bundle_ja.properties +++ /dev/null @@ -1,2 +0,0 @@ -UserArtifactIngestModuleFactory.moduleName=\u30AB\u30B9\u30BF\u30E0\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8\u8FFD\u52A0\u30C4\u30FC\u30EB -UserArtifactIngestModuleFactory.moduleDescription=\u30AB\u30B9\u30BF\u30E0\u306E\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8\u30BF\u30A4\u30D7\u3092\u8FFD\u52A0 \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/modules/UserArtifacts/UserArtifactIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/UserArtifacts/UserArtifactIngestModule.java deleted file mode 100755 index 5b510519ed..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/UserArtifacts/UserArtifactIngestModule.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2011-2016 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sleuthkit.autopsy.modules.UserArtifacts; - -import com.sun.media.jfxmedia.logging.Logger; -import java.util.List; -import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.casemodule.services.Blackboard.BlackboardException; -import org.sleuthkit.autopsy.casemodule.services.FileManager; -import org.sleuthkit.autopsy.ingest.DataSourceIngestModule; -import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress; -import org.sleuthkit.autopsy.ingest.IngestJobContext; -import org.sleuthkit.autopsy.ingest.IngestMessage; -import org.sleuthkit.autopsy.ingest.IngestServices; -import org.sleuthkit.datamodel.AbstractFile; -import org.sleuthkit.datamodel.BlackboardArtifact; -import org.sleuthkit.datamodel.BlackboardAttribute; -import org.sleuthkit.datamodel.BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE; -import org.sleuthkit.datamodel.Content; -import org.sleuthkit.datamodel.TskCoreException; - -/** - * Test module that creates new artifact and attribute types. - */ -public class UserArtifactIngestModule implements DataSourceIngestModule { - - private BlackboardArtifact.Type type1, type2; - - @Override - public ProcessResult process(Content dataSource, DataSourceIngestModuleProgress progressBar) { - progressBar.switchToDeterminate(2); - try { - FileManager manager = Case.getCurrentCase().getServices().getFileManager(); - List file1 = manager.findFiles("Sunset.jpg"); //NON-NLS - List file2 = manager.findFiles("Winter.jpg"); //NON-NLS - BlackboardArtifact art1; - BlackboardArtifact art2; - if (!file1.isEmpty()) { - art1 = file1.get(0).newArtifact(type1.getTypeID()); - } else { - art1 = dataSource.newArtifact(type1.getTypeID()); - } - if (!file2.isEmpty()) { - art2 = file2.get(0).newArtifact(type2.getTypeID()); - } else { - art2 = dataSource.newArtifact(type2.getTypeID()); - } - BlackboardAttribute.Type attributeType = Case.getCurrentCase().getServices().getBlackboard().addAttributeType("Test", TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.LONG, "2"); //NON-NLS - BlackboardAttribute.Type attributeType2 = Case.getCurrentCase().getServices().getBlackboard().addAttributeType("Test2", TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.BYTE, "3"); //NON-NLS - art1.addAttribute(new BlackboardAttribute(attributeType, - UserArtifactIngestModuleFactory.getModuleName(), -1L)); - progressBar.progress(1); - art2.addAttribute(new BlackboardAttribute(attributeType2, - UserArtifactIngestModuleFactory.getModuleName(), new byte[7])); - progressBar.progress(1); - IngestServices.getInstance().postMessage(IngestMessage.createDataMessage( - "name", // NON-NLS - UserArtifactIngestModuleFactory.getModuleName(), - "Test Results", //NON-NLS - "Test", //NON-NLS - art1)); - return ProcessResult.OK; - } catch (TskCoreException | BlackboardException ex) { - return ProcessResult.ERROR; - } - } - - @Override - public void startUp(IngestJobContext context) throws IngestModuleException { - try { - type1 = Case.getCurrentCase().getServices().getBlackboard().addArtifactType("This is", "a test"); //NON-NLS - type2 = Case.getCurrentCase().getServices().getBlackboard().addArtifactType("Another", "kinda test"); //NON-NLS - } catch (BlackboardException ex) { - Logger.logMsg(Logger.ERROR, "Startup failed"); //NON-NLS - } - } -} diff --git a/Core/src/org/sleuthkit/autopsy/modules/UserArtifacts/UserArtifactIngestModuleFactory.java b/Core/src/org/sleuthkit/autopsy/modules/UserArtifacts/UserArtifactIngestModuleFactory.java deleted file mode 100755 index b63d9f928a..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/UserArtifacts/UserArtifactIngestModuleFactory.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2011-2016 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sleuthkit.autopsy.modules.UserArtifacts; - -import org.openide.util.NbBundle; -import org.python.apache.xmlcommons.Version; -import org.sleuthkit.autopsy.ingest.DataSourceIngestModule; -import org.sleuthkit.autopsy.ingest.IngestModuleFactoryAdapter; -import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; - -/** - * Factory for test module that creates new artifact and attribute types. - */ -//@ServiceProvider(service = IngestModuleFactory.class) -public class UserArtifactIngestModuleFactory extends IngestModuleFactoryAdapter { - - static String getModuleName() { - return NbBundle.getMessage(UserArtifactIngestModuleFactory.class, "UserArtifactIngestModuleFactory.moduleName"); - } - - @Override - public String getModuleDisplayName() { - return getModuleName(); - } - - @Override - public String getModuleDescription() { - return NbBundle.getMessage(UserArtifactIngestModuleFactory.class, "UserArtifactIngestModuleFactory.moduleDescription"); - } - - @Override - public String getModuleVersionNumber() { - return Version.getVersion(); - } - - @Override - public DataSourceIngestModule createDataSourceIngestModule(IngestModuleIngestJobSettings ingestOptions) { - return new UserArtifactIngestModule(); - } - - @Override - public boolean isDataSourceIngestModuleFactory() { - return true; - } -} diff --git a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/Bundle.properties index 06b5b5a44f..e2e029d495 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/Bundle.properties @@ -35,6 +35,7 @@ EmbeddedFileExtractorIngestModule.ImageExtractor.pptContainer.init.err=Ppt conta EmbeddedFileExtractorIngestModule.ImageExtractor.pptxContainer.init.err=Pptx container could not be initialized while reading: {0} EmbeddedFileExtractorIngestModule.ImageExtractor.xlsContainer.init.err=Xls container could not be initialized while reading: {0} EmbeddedFileExtractorIngestModule.ImageExtractor.xlsxContainer.init.err=Xlsx container could not be initialized while reading: {0} +EmbeddedFileExtractorIngestModule.ImageExtractor.processing.err=Embedded File Extractor is unable to read content of {0} EmbeddedFileExtractorIngestModule.ImageExtractor.extractImage.addToDB.exception.msg=Unable to add the derived files to the database. EmbeddedFileExtractorIngestModule.ImageExtractor.getOutputFolderPath.exception.msg=Could not get path for image extraction from Abstract File\: {0} EmbeddedFileExtractorIngestModule.ImageExtractor.getOutputFolderPath.exception.msg=Could not get path for image extraction from Abstract File: {0} diff --git a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/EmbeddedFileExtractorIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/EmbeddedFileExtractorIngestModule.java index 7e0d220f11..b7f6529786 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/EmbeddedFileExtractorIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/EmbeddedFileExtractorIngestModule.java @@ -79,7 +79,7 @@ public final class EmbeddedFileExtractorIngestModule implements FileIngestModule } catch (SecurityException ex) { logger.log(Level.SEVERE, "Error initializing output dir: " + moduleDirAbsolute, ex); //NON-NLS services.postMessage(IngestMessage.createErrorMessage(EmbeddedFileExtractorModuleFactory.getModuleName(), "Error initializing", "Error initializing output dir: " + moduleDirAbsolute)); //NON-NLS - throw new IngestModuleException(ex.getMessage()); + throw new IngestModuleException(ex.getMessage(), ex); } } @@ -87,7 +87,7 @@ public final class EmbeddedFileExtractorIngestModule implements FileIngestModule try { fileTypeDetector = new FileTypeDetector(); } catch (FileTypeDetector.FileTypeDetectorInitException ex) { - throw new IngestModuleException(ex.getMessage()); + throw new IngestModuleException(ex.getMessage(), ex); } // initialize the extraction modules. diff --git a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/ImageExtractor.java b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/ImageExtractor.java index c916aa7f55..cb601c62a7 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/ImageExtractor.java +++ b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/ImageExtractor.java @@ -25,7 +25,6 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; -import org.apache.poi.OldFileFormatException; import org.apache.poi.hslf.model.Picture; import org.apache.poi.hslf.usermodel.PictureData; import org.apache.poi.hslf.usermodel.SlideShow; @@ -210,13 +209,23 @@ class ImageExtractor { HWPFDocument doc = null; try { doc = new HWPFDocument(new ReadContentInputStream(af)); - } catch (Throwable ex) { + } catch (Throwable ignore) { // instantiating POI containers throw RuntimeExceptions logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.docContainer.init.err", af.getName())); //NON-NLS return null; } - PicturesTable pictureTable = doc.getPicturesTable(); - List listOfAllPictures = pictureTable.getAllPictures(); + + PicturesTable pictureTable = null; + List listOfAllPictures = null; + try { + pictureTable = doc.getPicturesTable(); + listOfAllPictures = pictureTable.getAllPictures(); + } catch (Exception ignore) { + // log internal Java and Apache errors as WARNING + logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.processing.err", af.getName())); //NON-NLS + return null; + } + String outputFolderPath; if (listOfAllPictures.isEmpty()) { return null; @@ -227,9 +236,17 @@ class ImageExtractor { return null; } listOfExtractedImages = new ArrayList<>(); + byte[] data = null; for (org.apache.poi.hwpf.usermodel.Picture picture : listOfAllPictures) { String fileName = picture.suggestFullFileName(); - writeExtractedImage(Paths.get(outputFolderPath, fileName).toString(), picture.getContent()); + try { + data = picture.getContent(); + } catch (Exception ignore) { + // log internal Java and Apache errors as WARNING + logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.processing.err", af.getName())); //NON-NLS + return null; + } + writeExtractedImage(Paths.get(outputFolderPath, fileName).toString(), data); // TODO Extract more info from the Picture viz ctime, crtime, atime, mtime listOfExtractedImages.add(new ExtractedImage(fileName, getFileRelativePath(fileName), picture.getSize(), af)); } @@ -250,12 +267,19 @@ class ImageExtractor { XWPFDocument docx = null; try { docx = new XWPFDocument(new ReadContentInputStream(af)); - } catch (Throwable ex) { + } catch (Throwable ignore) { // instantiating POI containers throw RuntimeExceptions logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.docxContainer.init.err", af.getName())); //NON-NLS return null; } - List listOfAllPictures = docx.getAllPictures(); + List listOfAllPictures = null; + try { + listOfAllPictures = docx.getAllPictures(); + } catch (Exception ignore) { + // log internal Java and Apache errors as WARNING + logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.processing.err", af.getName())); //NON-NLS + return null; + } // if no images are extracted from the PPT, return null, else initialize // the output folder for image extraction. @@ -270,9 +294,17 @@ class ImageExtractor { return null; } listOfExtractedImages = new ArrayList<>(); + byte[] data = null; for (XWPFPictureData xwpfPicture : listOfAllPictures) { String fileName = xwpfPicture.getFileName(); - writeExtractedImage(Paths.get(outputFolderPath, fileName).toString(), xwpfPicture.getData()); + try { + data = xwpfPicture.getData(); + } catch (Exception ignore) { + // log internal Java and Apache errors as WARNING + logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.processing.err", af.getName())); //NON-NLS + return null; + } + writeExtractedImage(Paths.get(outputFolderPath, fileName).toString(), data); listOfExtractedImages.add(new ExtractedImage(fileName, getFileRelativePath(fileName), xwpfPicture.getData().length, af)); } return listOfExtractedImages; @@ -291,14 +323,21 @@ class ImageExtractor { SlideShow ppt = null; try { ppt = new SlideShow(new ReadContentInputStream(af)); - } catch (Throwable ex) { + } catch (Throwable ignore) { // instantiating POI containers throw RuntimeExceptions logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.pptContainer.init.err", af.getName())); //NON-NLS return null; } //extract all pictures contained in the presentation - PictureData[] listOfAllPictures = ppt.getPictureData(); + PictureData[] listOfAllPictures = null; + try { + listOfAllPictures = ppt.getPictureData(); + } catch (Exception ignore) { + // log internal Java and Apache errors as WARNING + logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.processing.err", af.getName())); //NON-NLS + return null; + } // if no images are extracted from the PPT, return null, else initialize // the output folder for image extraction. @@ -317,6 +356,7 @@ class ImageExtractor { // extraction path - outputFolder/image_number.ext int i = 0; listOfExtractedImages = new ArrayList<>(); + byte[] data = null; for (PictureData pictureData : listOfAllPictures) { // Get image extension, generate image name, write image to the module @@ -343,7 +383,14 @@ class ImageExtractor { continue; } String imageName = UNKNOWN_NAME_PREFIX + i + ext; //NON-NLS - writeExtractedImage(Paths.get(outputFolderPath, imageName).toString(), pictureData.getData()); + try { + data = pictureData.getData(); + } catch (Exception ignore) { + // log internal Java and Apache errors as WARNING + logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.processing.err", af.getName())); //NON-NLS + return null; + } + writeExtractedImage(Paths.get(outputFolderPath, imageName).toString(), data); listOfExtractedImages.add(new ExtractedImage(imageName, getFileRelativePath(imageName), pictureData.getData().length, af)); i++; } @@ -363,12 +410,19 @@ class ImageExtractor { XMLSlideShow pptx; try { pptx = new XMLSlideShow(new ReadContentInputStream(af)); - } catch (Throwable ex) { + } catch (Throwable ignore) { // instantiating POI containers throw RuntimeExceptions logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.pptxContainer.init.err", af.getName())); //NON-NLS return null; } - List listOfAllPictures = pptx.getAllPictures(); + List listOfAllPictures = null; + try { + listOfAllPictures = pptx.getAllPictures(); + } catch (Exception ignore) { + // log internal Java and Apache errors as WARNING + logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.processing.err", af.getName())); //NON-NLS + return null; + } // if no images are extracted from the PPT, return null, else initialize // the output folder for image extraction. @@ -384,12 +438,20 @@ class ImageExtractor { } listOfExtractedImages = new ArrayList<>(); + byte[] data = null; for (XSLFPictureData xslsPicture : listOfAllPictures) { // get image file name, write it to the module outputFolder, and add // it to the listOfExtractedImageAbstractFiles. String fileName = xslsPicture.getFileName(); - writeExtractedImage(Paths.get(outputFolderPath, fileName).toString(), xslsPicture.getData()); + try { + data = xslsPicture.getData(); + } catch (Exception ignore) { + // log internal Java and Apache errors as WARNING + logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.processing.err", af.getName())); //NON-NLS + return null; + } + writeExtractedImage(Paths.get(outputFolderPath, fileName).toString(), data); listOfExtractedImages.add(new ExtractedImage(fileName, getFileRelativePath(fileName), xslsPicture.getData().length, af)); } @@ -412,13 +474,21 @@ class ImageExtractor { Workbook xls; try { xls = new HSSFWorkbook(new ReadContentInputStream(af)); - } catch (Throwable ex) { + } catch (Throwable ignore) { // instantiating POI containers throw RuntimeExceptions - logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.xlsContainer.init.err", af.getName()) + af.getName()); //NON-NLS + logger.log(Level.WARNING, "{0}{1}", new Object[]{NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.xlsContainer.init.err", af.getName()), af.getName()}); //NON-NLS return null; } - List listOfAllPictures = xls.getAllPictures(); + List listOfAllPictures = null; + try { + listOfAllPictures = xls.getAllPictures(); + } catch (Exception ignore) { + // log internal Java and Apache errors as WARNING + logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.processing.err", af.getName())); //NON-NLS + return null; + } + // if no images are extracted from the PPT, return null, else initialize // the output folder for image extraction. String outputFolderPath; @@ -434,9 +504,17 @@ class ImageExtractor { int i = 0; listOfExtractedImages = new ArrayList<>(); + byte[] data = null; for (org.apache.poi.ss.usermodel.PictureData pictureData : listOfAllPictures) { String imageName = UNKNOWN_NAME_PREFIX + i + "." + pictureData.suggestFileExtension(); //NON-NLS - writeExtractedImage(Paths.get(outputFolderPath, imageName).toString(), pictureData.getData()); + try { + data = pictureData.getData(); + } catch (Exception ignore) { + // log internal Java and Apache errors as WARNING + logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.processing.err", af.getName())); //NON-NLS + return null; + } + writeExtractedImage(Paths.get(outputFolderPath, imageName).toString(), data); listOfExtractedImages.add(new ExtractedImage(imageName, getFileRelativePath(imageName), pictureData.getData().length, af)); i++; } @@ -457,13 +535,21 @@ class ImageExtractor { Workbook xlsx; try { xlsx = new XSSFWorkbook(new ReadContentInputStream(af)); - } catch (Throwable ex) { + } catch (Throwable ignore) { // instantiating POI containers throw RuntimeExceptions logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.xlsxContainer.init.err", af.getName())); //NON-NLS return null; } - List listOfAllPictures = xlsx.getAllPictures(); + List listOfAllPictures = null; + try { + listOfAllPictures = xlsx.getAllPictures(); + } catch (Exception ignore) { + // log internal Java and Apache errors as WARNING + logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.processing.err", af.getName())); //NON-NLS + return null; + } + // if no images are extracted from the PPT, return null, else initialize // the output folder for image extraction. String outputFolderPath; @@ -479,9 +565,17 @@ class ImageExtractor { int i = 0; listOfExtractedImages = new ArrayList<>(); + byte[] data = null; for (org.apache.poi.ss.usermodel.PictureData pictureData : listOfAllPictures) { String imageName = UNKNOWN_NAME_PREFIX + i + "." + pictureData.suggestFileExtension(); - writeExtractedImage(Paths.get(outputFolderPath, imageName).toString(), pictureData.getData()); + try { + data = pictureData.getData(); + } catch (Exception ignore) { + // log internal Java and Apache errors as WARNING + logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.processing.err", af.getName())); //NON-NLS + return null; + } + writeExtractedImage(Paths.get(outputFolderPath, imageName).toString(), data); listOfExtractedImages.add(new ExtractedImage(imageName, getFileRelativePath(imageName), pictureData.getData().length, af)); i++; } diff --git a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/SevenZipExtractor.java b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/SevenZipExtractor.java index 44052df224..881e7c5fa4 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/SevenZipExtractor.java +++ b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/SevenZipExtractor.java @@ -133,7 +133,7 @@ class SevenZipExtractor { String details = NbBundle.getMessage(SevenZipExtractor.class, "EmbeddedFileExtractorIngestModule.ArchiveExtractor.init.errCantInitLib", e.getMessage()); services.postMessage(IngestMessage.createErrorMessage(EmbeddedFileExtractorModuleFactory.getModuleName(), msg, details)); - throw new IngestModuleException(e.getMessage()); + throw new IngestModuleException(e.getMessage(), e); } } this.context = context; diff --git a/Core/src/org/sleuthkit/autopsy/modules/exif/ExifParserFileIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/exif/ExifParserFileIngestModule.java index de946ffd0f..b2ce0beca2 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/exif/ExifParserFileIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/exif/ExifParserFileIngestModule.java @@ -91,7 +91,7 @@ public final class ExifParserFileIngestModule implements FileIngestModule { try { fileTypeDetector = new FileTypeDetector(); } catch (FileTypeDetector.FileTypeDetectorInitException ex) { - throw new IngestModuleException(NbBundle.getMessage(this.getClass(), "ExifParserFileIngestModule.startUp.fileTypeDetectorInitializationException.msg")); + throw new IngestModuleException(NbBundle.getMessage(this.getClass(), "ExifParserFileIngestModule.startUp.fileTypeDetectorInitializationException.msg"), ex); } } diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties index 7c63074fbe..c85ead90b1 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties @@ -4,7 +4,6 @@ OptionsCategory_FileExtMismatch=File Extension Mismatch AddFileExtensionAction.msgDlg.msg=Writing XML configuration file failed. AddFileExtensionAction.msgDlg.title=Add Mismatch Extension Error AddFileExtensionAction.extHeaderLbl.text=Allowed Extensions for -FileExtMismatchConfigPanel.name.text=Advanced File Extension Mismatch Configuration FileExtMismatchConfigPanel.addExtButton.errLabel.empty=Extension text is empty\! FileExtMismatchConfigPanel.addExtButton.errLabel.noMimeType=No MIME type selected\! FileExtMismatchConfigPanel.addExtButton.errLabel.extExists=Extension already exists\! @@ -52,3 +51,4 @@ FileExtMismatchSettingsPanel.removeExtButton.text=Remove Selected Extension FileExtMismatchSettingsPanel.userTypeTextField.text= FileExtMismatchDetectorModuleFactory.getIngestJobSettingsPanel.exception.msg=Expected settings argument to be instanceof FileExtMismatchDetectorModuleSettings FileExtMismatchDetectorModuleFactory.createFileIngestModule.exception.msg=Expected settings argument to be instanceof FileExtMismatchDetectorModuleSettings +FileExtMismatchModuleSettingsPanel.skipKnownFiles.text=Skip known files diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle_ja.properties index 06cbd4336f..82aa0220c3 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle_ja.properties @@ -1,47 +1,46 @@ -OpenIDE-Module-Name=\u30D5\u30A1\u30A4\u30EB\u62E1\u5F35\u5B50\u4E0D\u4E00\u81F4 -OptionsCategory_Name_FileExtMismatchOptions=\u30D5\u30A1\u30A4\u30EB\u62E1\u5F35\u5B50\u4E0D\u4E00\u81F4 -OptionsCategory_FileExtMismatch=\u30D5\u30A1\u30A4\u30EB\u62E1\u5F35\u5B50\u4E0D\u4E00\u81F4 -AddFileExtensionAction.msgDlg.msg=XML\u8A2D\u5B9A\u30D5\u30A1\u30A4\u30EB\u3092\u66F8\u304F\u306E\u3092\u5931\u6557\u3057\u307E\u3057\u305F\u3002 -AddFileExtensionAction.msgDlg.title=\u4E0D\u4E00\u81F4\u62E1\u5F35\u5B50\u306E\u30A8\u30E9\u30FC\u3092\u8FFD\u52A0 -FileExtMismatchConfigPanel.name.text=\u30A2\u30C9\u30D0\u30F3\u30B9\u30D5\u30A1\u30A4\u30EB\u62E1\u5F35\u5B50\u4E0D\u4E00\u81F4\u306E\u8A2D\u5B9A -FileExtMismatchConfigPanel.addExtButton.errLabel.empty=\u62E1\u5F35\u5B50\u30C6\u30AD\u30B9\u30C8\u304C\u7A7A\u767D\u3067\u3059\uFF01 -FileExtMismatchConfigPanel.addExtButton.errLabel.noMimeType=MIME\u30BF\u30A4\u30D7\u304C\u9078\u629E\u3055\u308C\u3066\u3044\u307E\u305B\u3093\uFF01 -FileExtMismatchConfigPanel.addExtButton.errLabel.extExists=\u62E1\u5F35\u5B50\u306F\u3059\u3067\u306B\u5B58\u5728\u3057\u307E\u3059\uFF01 -FileExtMismatchConfigPanel.addExtButton.errLabel.extAdded=\u62E1\u5F35\u5B50{0}\u304C\u8FFD\u52A0\u3055\u308C\u307E\u3057\u305F\u3002 -FileExtMismatchConfigPanel.addTypeButton.empty=MIME\u30BF\u30A4\u30D7\u30C6\u30AD\u30B9\u30C8\u304C\u7A7A\u767D\u3067\u3059\uFF01 -FileExtMismatchConfigPanel.addTypeButton.mimeTypeNotSupported=MIME\u30BF\u30A4\u30D7\u304C\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u307E\u305B\u3093\uFF01 -FileExtMismatchConfigPanel.addTypeButton.mimeTypeExists=MIME\u30BF\u30A4\u30D7\u304C\u3059\u3067\u306B\u5B58\u5728\u3057\u307E\u3059\uFF01 -FileExtMismatchConfigPanel.addTypeButton.mimeTypeNotDetectable=MIME\u30BF\u30A4\u30D7\u304C\u3053\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u3067\u306F\u691C\u51FA\u3067\u304D\u307E\u305B\u3093\u3002 -FileExtMismatchConfigPanel.addTypeButton.mimeTypeAdded=MIME\u30BF\u30A4\u30D7{0}\u304C\u8FFD\u52A0\u3055\u308C\u307E\u3057\u305F\u3002 -FileExtMismatchConfigPanel.removeTypeButton.noneSelected=MIME\u30BF\u30A4\u30D7\u304C\u9078\u629E\u3055\u308C\u3066\u3044\u307E\u305B\u3093\uFF01 -FileExtMismatchConfigPanel.remoteTypeButton.deleted=MIME\u30BF\u30A4\u30D7{0}\u304C\u524A\u9664\u3055\u308C\u307E\u3057\u305F\u3002 -FileExtMismatchConfigPanel.removeExtButton.noneSelected=\u62E1\u5F35\u5B50\u304C\u9078\u629E\u3055\u308C\u3066\u3044\u307E\u305B\u3093\uFF01 -FileExtMismatchConfigPanel.removeExtButton.noMimeTypeSelected=MIME\u30BF\u30A4\u30D7\u304C\u9078\u629E\u3055\u308C\u3066\u3044\u307E\u305B\u3093\uFF01 -FileExtMismatchConfigPanel.removeExtButton.deleted=\u62E1\u5F35\u5B50{0}\u304C\u524A\u9664\u3055\u308C\u307E\u3057\u305F\u3002 -FileExtMismatchConfigPanel.store.msg=\u4FDD\u5B58\u3055\u308C\u307E\u3057\u305F\u3002 -FileExtMismatchConfigPanel.store.msgDlg.msg=XML\u8A2D\u5B9A\u30D5\u30A1\u30A4\u30EB\u3092\u66F8\u304F\u306E\u3092\u5931\u6557\u3057\u307E\u3057\u305F\u3002 -FileExtMismatchConfigPanel.save.msgDlg.title=\u4FDD\u5B58\u30A8\u30E9\u30FC -FileExtMismatchConfigPanel.ok.confDlg.msg=\u8A2D\u5B9A\u5909\u66F4\u3092\u4FDD\u5B58\u3057\u307E\u3059\u304B\uFF1F -FileExtMismatchConfigPanel.confDlg.title=\u4FDD\u5B58\u3055\u308C\u3066\u3044\u306A\u3044\u5909\u66F4 -FileExtMismatchConfigPanel.mimeTableModel.colName=MIME\u30BF\u30A4\u30D7 -FileExtMismatchConfigPanel.extTableModel.colName=\u62E1\u5F35\u5B50 -FileExtMismatchContextMenuActionsProvider.menuItemStr=\u62E1\u5F35\u5B50{0}\u3092MIME\u30BF\u30A4\u30D7{1}\u306E\u4E00\u81F4\u3068\u3057\u3066\u8FFD\u52A0 -FileExtMismatchIngestModule.moduleName=\u62E1\u5F35\u5B50\u4E0D\u4E00\u81F4\u30C7\u30A3\u30C6\u30AF\u30BF\u30FC -FileExtMismatchIngestModule.moduleDesc.text=\u30D5\u30A1\u30A4\u30EB\u30BF\u30A4\u30D7\u306B\u57FA\u3065\u3044\u3066\u3001\u6A19\u6E96\u7684\u3067\u306F\u306A\u3044\u62E1\u5F35\u5B50\u3092\u6301\u3064\u30D5\u30A1\u30A4\u30EB\u3092\u30D5\u30E9\u30B0\u3057\u307E\u3059\u3002d -FileExtMismatchIngestModule.complete.totalProcTime=\u5408\u8A08\u51E6\u7406\u6642\u9593 -FileExtMismatchIngestModule.complete.totalFiles=\u5408\u8A08\u51E6\u7406\u30D5\u30A1\u30A4\u30EB\u6570 -FileExtMismatchIngestModule.complete.svcMsg.text=\u30D5\u30A1\u30A4\u30EB\u62E1\u5F35\u5B50\u4E0D\u4E00\u81F4\u7D50\u679C -FileExtMismatchOptionsPanelController.moduleErr=\u30E2\u30B8\u30E5\u30FC\u30EB\u30A8\u30E9\u30FC -FileExtMismatchOptionsPanelController.moduleErr.msg=FileExtMismatchOptionsPanelController\u30A2\u30C3\u30D7\u30C7\u30FC\u30C8\u306E\u78BA\u8A8D\u4E2D\u306B\u30E2\u30B8\u30E5\u30FC\u30EB\u304C\u30A8\u30E9\u30FC\u3092\u8D77\u3053\u3057\u307E\u3057\u305F\u3002\u3069\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u304B\u30ED\u30B0\u3092\u78BA\u8A8D\u3057\u3066\u4E0B\u3055\u3044\u3002\u4E00\u90E8\u306E\u30C7\u30FC\u30BF\u304C\u4E0D\u5B8C\u5168\u304B\u3082\u3057\u308C\u307E\u305B\u3093\u3002 -AddFileExtensionAction.extHeaderLbl.text=\u4E0B\u8A18\u7528\u306B\u8A31\u53EF\u3059\u308B\u62E1\u5F35\u5B50 -FileExtMismatchModuleSettingsPanel.skipTextPlain.text=\u30C6\u30AD\u30B9\u30C8\u30D5\u30A1\u30A4\u30EB\u3092\u30B9\u30AD\u30C3\u30D7 -FileExtMismatchModuleSettingsPanel.skipNoExtCheckBox.text=\u62E1\u5F35\u5B50\u306E\u7121\u3044\u30D5\u30A1\u30A4\u30EB\u3092\u30B9\u30AD\u30C3\u30D7 -FileExtMismatchSettingsPanel.addTypeButton.text=\u30BF\u30A4\u30D7\u3092\u8FFD\u52A0 -FileExtMismatchSettingsPanel.extHeaderLabel.text=\u8A31\u53EF\u3059\u308B\u62E1\u5F35\u5B50\uFF1A -FileExtMismatchSettingsPanel.removeTypeButton.text=\u9078\u629E\u3057\u305F\u30BF\u30A4\u30D7\u3092\u524A\u9664 -FileExtMismatchSettingsPanel.saveButton.text=\u8A2D\u5B9A\u3092\u4FDD\u5B58 -FileExtMismatchSettingsPanel.jLabel1.text=\u30D5\u30A1\u30A4\u30EB\u30BF\u30A4\u30D7\uFF1A -FileExtMismatchSettingsPanel.addExtButton.text=\u62E1\u5F35\u5B50\u3092\u8FFD\u52A0 -FileExtMismatchSettingsPanel.removeExtButton.text=\u9078\u629E\u3057\u305F\u62E1\u5F35\u5B50\u3092\u524A\u9664 -FileExtMismatchDetectorModuleFactory.getIngestJobSettingsPanel.exception.msg=\u8A2D\u5B9A\u3092\u884C\u3046\u70BA\u306E\u60F3\u5B9A\u3055\u308C\u308B\u5F15\u6570\u306Finstanceof FileExtMismatchDetectorModuleSettings\u3067\u3059\u3002 -FileExtMismatchDetectorModuleFactory.createFileIngestModule.exception.msg=\u8A2D\u5B9A\u3092\u884C\u3046\u70BA\u306E\u60F3\u5B9A\u3055\u308C\u308B\u5F15\u6570\u306Finstanceof FileExtMismatchDetectorModuleSettings\u3067\u3059\u3002 +OpenIDE-Module-Name=\u30d5\u30a1\u30a4\u30eb\u62e1\u5f35\u5b50\u4e0d\u4e00\u81f4 +OptionsCategory_Name_FileExtMismatchOptions=\u30d5\u30a1\u30a4\u30eb\u62e1\u5f35\u5b50\u4e0d\u4e00\u81f4 +OptionsCategory_FileExtMismatch=\u30d5\u30a1\u30a4\u30eb\u62e1\u5f35\u5b50\u4e0d\u4e00\u81f4 +AddFileExtensionAction.msgDlg.msg=XML\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\u3092\u66f8\u304f\u306e\u3092\u5931\u6557\u3057\u307e\u3057\u305f\u3002 +AddFileExtensionAction.msgDlg.title=\u4e0d\u4e00\u81f4\u62e1\u5f35\u5b50\u306e\u30a8\u30e9\u30fc\u3092\u8ffd\u52a0 +FileExtMismatchConfigPanel.addExtButton.errLabel.empty=\u62e1\u5f35\u5b50\u30c6\u30ad\u30b9\u30c8\u304c\u7a7a\u767d\u3067\u3059\uff01 +FileExtMismatchConfigPanel.addExtButton.errLabel.noMimeType=MIME\u30bf\u30a4\u30d7\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u307e\u305b\u3093\uff01 +FileExtMismatchConfigPanel.addExtButton.errLabel.extExists=\u62e1\u5f35\u5b50\u306f\u3059\u3067\u306b\u5b58\u5728\u3057\u307e\u3059\uff01 +FileExtMismatchConfigPanel.addExtButton.errLabel.extAdded=\u62e1\u5f35\u5b50{0}\u304c\u8ffd\u52a0\u3055\u308c\u307e\u3057\u305f\u3002 +FileExtMismatchConfigPanel.addTypeButton.empty=MIME\u30bf\u30a4\u30d7\u30c6\u30ad\u30b9\u30c8\u304c\u7a7a\u767d\u3067\u3059\uff01 +FileExtMismatchConfigPanel.addTypeButton.mimeTypeNotSupported=MIME\u30bf\u30a4\u30d7\u304c\u30b5\u30dd\u30fc\u30c8\u3055\u308c\u3066\u3044\u307e\u305b\u3093\uff01 +FileExtMismatchConfigPanel.addTypeButton.mimeTypeExists=MIME\u30bf\u30a4\u30d7\u304c\u3059\u3067\u306b\u5b58\u5728\u3057\u307e\u3059\uff01 +FileExtMismatchConfigPanel.addTypeButton.mimeTypeNotDetectable=MIME\u30bf\u30a4\u30d7\u304c\u3053\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u3067\u306f\u691c\u51fa\u3067\u304d\u307e\u305b\u3093\u3002 +FileExtMismatchConfigPanel.addTypeButton.mimeTypeAdded=MIME\u30bf\u30a4\u30d7{0}\u304c\u8ffd\u52a0\u3055\u308c\u307e\u3057\u305f\u3002 +FileExtMismatchConfigPanel.removeTypeButton.noneSelected=MIME\u30bf\u30a4\u30d7\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u307e\u305b\u3093\uff01 +FileExtMismatchConfigPanel.remoteTypeButton.deleted=MIME\u30bf\u30a4\u30d7{0}\u304c\u524a\u9664\u3055\u308c\u307e\u3057\u305f\u3002 +FileExtMismatchConfigPanel.removeExtButton.noneSelected=\u62e1\u5f35\u5b50\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u307e\u305b\u3093\uff01 +FileExtMismatchConfigPanel.removeExtButton.noMimeTypeSelected=MIME\u30bf\u30a4\u30d7\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u307e\u305b\u3093\uff01 +FileExtMismatchConfigPanel.removeExtButton.deleted=\u62e1\u5f35\u5b50{0}\u304c\u524a\u9664\u3055\u308c\u307e\u3057\u305f\u3002 +FileExtMismatchConfigPanel.store.msg=\u4fdd\u5b58\u3055\u308c\u307e\u3057\u305f\u3002 +FileExtMismatchConfigPanel.store.msgDlg.msg=XML\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\u3092\u66f8\u304f\u306e\u3092\u5931\u6557\u3057\u307e\u3057\u305f\u3002 +FileExtMismatchConfigPanel.save.msgDlg.title=\u4fdd\u5b58\u30a8\u30e9\u30fc +FileExtMismatchConfigPanel.ok.confDlg.msg=\u8a2d\u5b9a\u5909\u66f4\u3092\u4fdd\u5b58\u3057\u307e\u3059\u304b\uff1f +FileExtMismatchConfigPanel.confDlg.title=\u4fdd\u5b58\u3055\u308c\u3066\u3044\u306a\u3044\u5909\u66f4 +FileExtMismatchConfigPanel.mimeTableModel.colName=MIME\u30bf\u30a4\u30d7 +FileExtMismatchConfigPanel.extTableModel.colName=\u62e1\u5f35\u5b50 +FileExtMismatchContextMenuActionsProvider.menuItemStr=\u62e1\u5f35\u5b50{0}\u3092MIME\u30bf\u30a4\u30d7{1}\u306e\u4e00\u81f4\u3068\u3057\u3066\u8ffd\u52a0 +FileExtMismatchIngestModule.moduleName=\u62e1\u5f35\u5b50\u4e0d\u4e00\u81f4\u30c7\u30a3\u30c6\u30af\u30bf\u30fc +FileExtMismatchIngestModule.moduleDesc.text=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\u306b\u57fa\u3065\u3044\u3066\u3001\u6a19\u6e96\u7684\u3067\u306f\u306a\u3044\u62e1\u5f35\u5b50\u3092\u6301\u3064\u30d5\u30a1\u30a4\u30eb\u3092\u30d5\u30e9\u30b0\u3057\u307e\u3059\u3002d +FileExtMismatchIngestModule.complete.totalProcTime=\u5408\u8a08\u51e6\u7406\u6642\u9593 +FileExtMismatchIngestModule.complete.totalFiles=\u5408\u8a08\u51e6\u7406\u30d5\u30a1\u30a4\u30eb\u6570 +FileExtMismatchIngestModule.complete.svcMsg.text=\u30d5\u30a1\u30a4\u30eb\u62e1\u5f35\u5b50\u4e0d\u4e00\u81f4\u7d50\u679c +FileExtMismatchOptionsPanelController.moduleErr=\u30e2\u30b8\u30e5\u30fc\u30eb\u30a8\u30e9\u30fc +FileExtMismatchOptionsPanelController.moduleErr.msg=FileExtMismatchOptionsPanelController\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u306e\u78ba\u8a8d\u4e2d\u306b\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u30a8\u30e9\u30fc\u3092\u8d77\u3053\u3057\u307e\u3057\u305f\u3002\u3069\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u304b\u30ed\u30b0\u3092\u78ba\u8a8d\u3057\u3066\u4e0b\u3055\u3044\u3002\u4e00\u90e8\u306e\u30c7\u30fc\u30bf\u304c\u4e0d\u5b8c\u5168\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002 +AddFileExtensionAction.extHeaderLbl.text=\u4e0b\u8a18\u7528\u306b\u8a31\u53ef\u3059\u308b\u62e1\u5f35\u5b50 +FileExtMismatchModuleSettingsPanel.skipTextPlain.text=\u30c6\u30ad\u30b9\u30c8\u30d5\u30a1\u30a4\u30eb\u3092\u30b9\u30ad\u30c3\u30d7 +FileExtMismatchModuleSettingsPanel.skipNoExtCheckBox.text=\u62e1\u5f35\u5b50\u306e\u7121\u3044\u30d5\u30a1\u30a4\u30eb\u3092\u30b9\u30ad\u30c3\u30d7 +FileExtMismatchSettingsPanel.addTypeButton.text=\u30bf\u30a4\u30d7\u3092\u8ffd\u52a0 +FileExtMismatchSettingsPanel.extHeaderLabel.text=\u8a31\u53ef\u3059\u308b\u62e1\u5f35\u5b50\uff1a +FileExtMismatchSettingsPanel.removeTypeButton.text=\u9078\u629e\u3057\u305f\u30bf\u30a4\u30d7\u3092\u524a\u9664 +FileExtMismatchSettingsPanel.saveButton.text=\u8a2d\u5b9a\u3092\u4fdd\u5b58 +FileExtMismatchSettingsPanel.jLabel1.text=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\uff1a +FileExtMismatchSettingsPanel.addExtButton.text=\u62e1\u5f35\u5b50\u3092\u8ffd\u52a0 +FileExtMismatchSettingsPanel.removeExtButton.text=\u9078\u629e\u3057\u305f\u62e1\u5f35\u5b50\u3092\u524a\u9664 +FileExtMismatchDetectorModuleFactory.getIngestJobSettingsPanel.exception.msg=\u8a2d\u5b9a\u3092\u884c\u3046\u70ba\u306e\u60f3\u5b9a\u3055\u308c\u308b\u5f15\u6570\u306finstanceof FileExtMismatchDetectorModuleSettings\u3067\u3059\u3002 +FileExtMismatchDetectorModuleFactory.createFileIngestModule.exception.msg=\u8a2d\u5b9a\u3092\u884c\u3046\u70ba\u306e\u60f3\u5b9a\u3055\u308c\u308b\u5f15\u6570\u306finstanceof FileExtMismatchDetectorModuleSettings\u3067\u3059\u3002 diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchDetectorModuleSettings.java b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchDetectorModuleSettings.java index 22074222a5..0efbd24db8 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchDetectorModuleSettings.java +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchDetectorModuleSettings.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2014 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,6 +18,8 @@ */ package org.sleuthkit.autopsy.modules.fileextmismatch; +import java.io.IOException; +import java.io.ObjectInputStream; import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; /** @@ -26,15 +28,21 @@ import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; final class FileExtMismatchDetectorModuleSettings implements IngestModuleIngestJobSettings { private static final long serialVersionUID = 1L; - private boolean skipFilesWithNoExtension = true; - private boolean skipFilesWithTextPlainMimeType = true; + private long versionNumber; + private boolean skipFilesWithNoExtension; + private boolean skipFilesWithTextPlainMimeType; + private boolean skipKnownFiles; FileExtMismatchDetectorModuleSettings() { + this.skipFilesWithNoExtension = true; + this.skipFilesWithTextPlainMimeType = true; + this.skipKnownFiles = true; } FileExtMismatchDetectorModuleSettings(boolean skipKnownFiles, boolean skipFilesWithNoExtension, boolean skipFilesWithTextPlainMimeType) { this.skipFilesWithNoExtension = skipFilesWithNoExtension; this.skipFilesWithTextPlainMimeType = skipFilesWithTextPlainMimeType; + this.skipKnownFiles = skipKnownFiles; } @Override @@ -42,19 +50,41 @@ final class FileExtMismatchDetectorModuleSettings implements IngestModuleIngestJ return serialVersionUID; } - void setSkipFilesWithNoExtension(boolean enabled) { - skipFilesWithNoExtension = enabled; + void setSkipFilesWithNoExtension(boolean skipFilesWithNoExtension) { + this.skipFilesWithNoExtension = skipFilesWithNoExtension; } boolean skipFilesWithNoExtension() { return skipFilesWithNoExtension; } - void setSkipFilesWithTextPlainMimeType(boolean enabled) { - skipFilesWithTextPlainMimeType = enabled; + void setSkipFilesWithTextPlainMimeType(boolean skipFilesWithTextPlainMimeType) { + this.skipFilesWithTextPlainMimeType = skipFilesWithTextPlainMimeType; } boolean skipFilesWithTextPlainMimeType() { return skipFilesWithTextPlainMimeType; } + + boolean skipKnownFiles() { + return skipKnownFiles; + } + + void setSkipKnownFiles(boolean skipKnownFiles) { + this.skipKnownFiles = skipKnownFiles; + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + if (0L == versionNumber) { + /* + * If the version number is set to the Java field default value of + * zero, then skipKnownFiles is a new field. Change this to the + * desired default value of true. + */ + skipKnownFiles = true; + } + versionNumber = 1; + } + } diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchIngestModule.java index e22e73ae26..a3b54e8d41 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchIngestModule.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2014 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,13 +18,11 @@ */ package org.sleuthkit.autopsy.modules.fileextmismatch; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.logging.Level; -import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.services.Blackboard; @@ -40,9 +38,9 @@ import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; -import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; +import org.sleuthkit.datamodel.TskData.FileKnown; import org.sleuthkit.datamodel.TskException; /** @@ -58,6 +56,7 @@ public class FileExtMismatchIngestModule implements FileIngestModule { private static final HashMap totalsForIngestJobs = new HashMap<>(); private static final IngestModuleReferenceCounter refCounter = new IngestModuleReferenceCounter(); private static Blackboard blackboard; + private FileTypeDetector detector; private static class IngestJobTotals { @@ -94,12 +93,20 @@ public class FileExtMismatchIngestModule implements FileIngestModule { FileExtMismatchXML xmlLoader = FileExtMismatchXML.getDefault(); SigTypeToExtMap = xmlLoader.load(); + try { + this.detector = new FileTypeDetector(); + } catch (FileTypeDetector.FileTypeDetectorInitException ex) { + throw new IngestModuleException("Could not create file type detector.", ex); + } } @Override public ProcessResult process(AbstractFile abstractFile) { blackboard = Case.getCurrentCase().getServices().getBlackboard(); + if(this.settings.skipKnownFiles() && (abstractFile.getKnown() == FileKnown.KNOWN)) { + return ProcessResult.OK; + } // skip non-files if ((abstractFile.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) @@ -157,7 +164,7 @@ public class FileExtMismatchIngestModule implements FileIngestModule { if (settings.skipFilesWithNoExtension() && currActualExt.isEmpty()) { return false; } - String currActualSigType = abstractFile.getMIMEType(); + String currActualSigType = detector.getFileType(abstractFile); if (currActualSigType == null) { return false; } diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchModuleSettingsPanel.form b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchModuleSettingsPanel.form index be70dbe504..4974e318bd 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchModuleSettingsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchModuleSettingsPanel.form @@ -21,6 +21,7 @@ + @@ -32,7 +33,9 @@ - + + + @@ -62,5 +65,16 @@ + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchModuleSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchModuleSettingsPanel.java index de619e3510..4ecde417ce 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchModuleSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchModuleSettingsPanel.java @@ -38,6 +38,7 @@ final class FileExtMismatchModuleSettingsPanel extends IngestModuleIngestJobSett private void customizeComponents() { skipNoExtCheckBox.setSelected(settings.skipFilesWithNoExtension()); skipTextPlain.setSelected(settings.skipFilesWithTextPlainMimeType()); + skipKnownFiles.setSelected(settings.skipKnownFiles()); } @Override @@ -56,6 +57,7 @@ final class FileExtMismatchModuleSettingsPanel extends IngestModuleIngestJobSett skipNoExtCheckBox = new javax.swing.JCheckBox(); skipTextPlain = new javax.swing.JCheckBox(); + skipKnownFiles = new javax.swing.JCheckBox(); skipNoExtCheckBox.setSelected(true); skipNoExtCheckBox.setText(org.openide.util.NbBundle.getMessage(FileExtMismatchModuleSettingsPanel.class, "FileExtMismatchModuleSettingsPanel.skipNoExtCheckBox.text")); // NOI18N @@ -73,6 +75,14 @@ final class FileExtMismatchModuleSettingsPanel extends IngestModuleIngestJobSett } }); + skipKnownFiles.setSelected(true); + skipKnownFiles.setText(org.openide.util.NbBundle.getMessage(FileExtMismatchModuleSettingsPanel.class, "FileExtMismatchModuleSettingsPanel.skipKnownFiles.text")); // NOI18N + skipKnownFiles.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + skipKnownFilesActionPerformed(evt); + } + }); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( @@ -81,7 +91,8 @@ final class FileExtMismatchModuleSettingsPanel extends IngestModuleIngestJobSett .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(skipTextPlain) - .addComponent(skipNoExtCheckBox)) + .addComponent(skipNoExtCheckBox) + .addComponent(skipKnownFiles)) .addGap(0, 138, Short.MAX_VALUE)) ); layout.setVerticalGroup( @@ -90,7 +101,9 @@ final class FileExtMismatchModuleSettingsPanel extends IngestModuleIngestJobSett .addComponent(skipNoExtCheckBox) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(skipTextPlain) - .addContainerGap(51, Short.MAX_VALUE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(skipKnownFiles) + .addContainerGap(28, Short.MAX_VALUE)) ); }// //GEN-END:initComponents @@ -102,7 +115,12 @@ final class FileExtMismatchModuleSettingsPanel extends IngestModuleIngestJobSett settings.setSkipFilesWithTextPlainMimeType(skipTextPlain.isSelected()); }//GEN-LAST:event_skipTextPlainActionPerformed + private void skipKnownFilesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_skipKnownFilesActionPerformed + settings.setSkipKnownFiles(skipKnownFiles.isSelected()); + }//GEN-LAST:event_skipKnownFilesActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JCheckBox skipKnownFiles; private javax.swing.JCheckBox skipNoExtCheckBox; private javax.swing.JCheckBox skipTextPlain; // End of variables declaration//GEN-END:variables diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettingsPanel.java index fa0a090fdc..1de79557bc 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchSettingsPanel.java @@ -69,8 +69,9 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel customizeComponents(); } + @NbBundle.Messages({"FileExtMismatchSettingsPanel.Title=Global File Extension Mismatch Identification Settings"}) private void customizeComponents() { - setName(NbBundle.getMessage(this.getClass(), "FileExtMismatchConfigPanel.name.text")); + setName(Bundle.FileExtMismatchSettingsPanel_Title()); // Handle selections on the left table lsm = mimeTable.getSelectionModel(); diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties index bf6adc0de3..ccc1bd0aff 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties @@ -44,9 +44,8 @@ FileTypeIdGlobalSettingsPanel.ingestRunningWarningLabel.text=Cannot make changes UserDefinedFileTypesManager.loadFileTypes.errorMessage=Failed to load existing file type definitions. UserDefinedFileTypesManager.saveFileTypes.errorMessage=Failed to save file type definitions. FileTypeIdGlobalSettingsPanel.newTypeButton.text=New -FileTypeIdGlobalSettingsPanel.jLabel1.text=Custom File Types -FileTypeIdGlobalSettingsPanel.jLabel2.text=MIME Types: +FileTypeIdGlobalSettingsPanel.jLabel2.text=Custom MIME Types: FileTypeIdGlobalSettingsPanel.jLabel3.text=Autopsy can automatically detect many file types. Add your custom file types here. FileTypeIdGlobalSettingsPanel.startUp.fileTypeDetectorInitializationException.msg=Error initializing the file type detector. FileTypeIdIngestModule.startUp.fileTypeDetectorInitializationException.msg=Error initializing the file type detector. -FileTypeIdGlobalSettingsPanel.offsetRelativeToLabel.text=Offset is relative to +FileTypeIdGlobalSettingsPanel.offsetRelativeToLabel.text=Offset is relative to diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle_ja.properties index dd67259dae..a5f9b02e62 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/Bundle_ja.properties @@ -1,47 +1,46 @@ -OpenIDE-Module-Name=\u30D5\u30A1\u30A4\u30EB\u30BF\u30A4\u30D7ID -FileTypeIdIngestModule.moduleName.text=\u30D5\u30A1\u30A4\u30EB\u30BF\u30A4\u30D7\u306E\u7279\u5B9A -FileTypeIdIngestModule.moduleDesc.text=\u30D0\u30A4\u30CA\u30EA\u30B7\u30B0\u30CD\u30C1\u30E3\u306B\u57FA\u3065\u3044\u3066\u30D5\u30A1\u30A4\u30EB\u30BF\u30A4\u30D7\u3092\u4E00\u81F4\u3057\u307E\u3059\u3002 -FileTypeIdIngestModule.complete.totalProcTime=\u5408\u8A08\u51E6\u7406\u6642\u9593 -FileTypeIdIngestModule.complete.totalFiles=\u5408\u8A08\u51E6\u7406\u30D5\u30A1\u30A4\u30EB\u6570 -FileTypeIdIngestModule.complete.srvMsg.text=\u30D5\u30A1\u30A4\u30EB\u30BF\u30A4\u30D7ID\u306E\u7D50\u679C -FileTypeIdModuleFactory.getIngestJobSettingsPanel.exception.msg=\u8A2D\u5B9A\u3092\u884C\u3046\u70BA\u306E\u60F3\u5B9A\u3055\u308C\u308B\u5F15\u6570\u306Finstanceof FileTypeIdModuleSettings\u3067\u3059\u3002 -FileTypeIdModuleFactory.createFileIngestModule.exception.msg=\u8A2D\u5B9A\u3092\u884C\u3046\u70BA\u306E\u60F3\u5B9A\u3055\u308C\u308B\u5F15\u6570\u306Finstanceof FileTypeIdModuleSettings\u3067\u3059\u3002 -FileTypeIdIngestJobSettingsPanel.skipKnownCheckBox.toolTipText=\u65E2\u77E5\u306E\u30CF\u30C3\u30B7\u30E5\u5024\u3092\u6301\u3064\u30D5\u30A1\u30A4\u30EB\u6570\u306B\u3088\u3063\u3066\u306F\u3001\u3053\u306E\u30DC\u30C3\u30AF\u30B9\u3092\u9078\u629E\u3059\u308B\u3053\u3068\u306B\u3088\u308A\u3001\u30D5\u30A1\u30A4\u30EB\u30BF\u30A4\u30D7\u306E\u7279\u5B9A\u3092\u52A0\u901F\u3057\u307E\u3059\u3002 -FileTypeIdIngestJobSettingsPanel.skipKnownCheckBox.text=\u65E2\u77E5\u30D5\u30A1\u30A4\u30EB\uFF08NSRL\uFF09\u3092\u30B9\u30AD\u30C3\u30D7 -FileTypeIdGlobalSettingsPanel.deleteTypeButton.text=\u524A\u9664 -FileTypeIdGlobalSettingsPanel.filesSetNameLabel.text=\u30BB\u30C3\u30C8\u540D -FileTypeIdGlobalSettingsPanel.ingestRunningWarningLabel.text=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u3092\u5B9F\u884C\u4E2D\u306B\u30D5\u30A1\u30A4\u30EB\u30BF\u30A4\u30D7\u5B9A\u7FA9\u3092\u5909\u66F4\u3067\u304D\u307E\u305B\u3093\uFF01 -FileTypeIdGlobalSettingsPanel.JOptionPane.invalidInterestingFilesSetName.title=\u7591\u308F\u3057\u3044\u30D5\u30A1\u30A4\u30EB\u30BB\u30C3\u30C8\u540D\u304C\u6B20\u3051\u3066\u3044\u307E\u3059 -FileTypeIdGlobalSettingsPanel.JOptionPane.invalidMIMEType.message=MIME\u30BF\u30A4\u30D7\u304C\u5FC5\u8981\u3067\u3059\u3002 -FileTypeIdGlobalSettingsPanel.JOptionPane.invalidMIMEType.title=MIME\u30BF\u30A4\u30D7\u304C\u6B20\u3051\u3066\u3044\u307E\u3059 -FileTypeIdGlobalSettingsPanel.JOptionPane.invalidOffset.message=\u30AA\u30D5\u30BB\u30C3\u30C8\u306F\u6B63\u6574\u6570\u3067\u306A\u3051\u308C\u3070\u3044\u3051\u307E\u305B\u3093\u3002 -FileTypeIdGlobalSettingsPanel.JOptionPane.invalidOffset.title=\u7121\u52B9\u306A\u30AA\u30D5\u30BB\u30C3\u30C8 -FileTypeIdGlobalSettingsPanel.JOptionPane.invalidRawSignatureBytes.message=\u3053\u306E\u30B7\u30B0\u30CD\u30C1\u30E3\u306B\u4E00\u3064\u4EE5\u4E0A\u306E\u7121\u52B9\u306A16\u9032\u6570\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\u3002 -FileTypeIdGlobalSettingsPanel.JOptionPane.invalidSignature.message=\u30B7\u30B0\u30CD\u30C1\u30E3\u304C\u5FC5\u8981\u3067\u3059\u3002 -FileTypeIdGlobalSettingsPanel.JOptionPane.invalidSignature.title=\u30B7\u30B0\u30CD\u30C1\u30E3\u304C\u6B20\u3051\u3066\u3044\u307E\u3059 -FileTypeIdGlobalSettingsPanel.JOptionPane.invalidSignatureBytes.title=\u30B7\u30B0\u30CD\u30C1\u30E3\u304C\u7121\u52B9\u3067\u3059 -FileTypeIdGlobalSettingsPanel.JOptionPane.loadFailed.title=\u8AAD\u307F\u8FBC\u307F\u304C\u5931\u6557\u3057\u307E\u3057\u305F -FileTypeIdGlobalSettingsPanel.JOptionPane.storeFailed.title=\u4FDD\u5B58\u304C\u5931\u6557\u3057\u307E\u3057\u305F -FileTypeIdGlobalSettingsPanel.mimeTypeLabel.text=MIME\u30BF\u30A4\u30D7 -FileTypeIdGlobalSettingsPanel.newTypeButton.text=\u65B0\u898F\u30BF\u30A4\u30D7 -FileTypeIdGlobalSettingsPanel.offsetLabel.text=\u30D0\u30A4\u30C8\u30AA\u30D5\u30BB\u30C3\u30C8 -FileTypeIdGlobalSettingsPanel.postHitCheckBox.text=\u767A\u898B\u3057\u305F\u969B\u306B\u300C\u7591\u308F\u3057\u3044\u30D5\u30A1\u30A4\u30EB\u300D\u3068\u8B66\u544A -FileTypeIdGlobalSettingsPanel.saveTypeButton.text=\u4FDD\u5B58\u30BF\u30A4\u30D7 -FileTypeIdGlobalSettingsPanel.signatureComboBox.asciiItem=\u30B9\u30C8\u30EA\u30F3\u30B0\uFF08ASCII\uFF09 -FileTypeIdGlobalSettingsPanel.signatureComboBox.rawItem=\u30D0\u30A4\u30C8\uFF08HEX\uFF09 -FileTypeIdGlobalSettingsPanel.signatureLabel.text=\u30B7\u30B0\u30CD\u30C1\u30E3 -FileTypeIdGlobalSettingsPanel.signatureTypeLabel.text=\u30B7\u30B0\u30CD\u30C1\u30E3\u30BF\u30A4\u30D7 -OptionsCategory_Keywords_FileTypeId=\u30D5\u30A1\u30A4\u30EB\u30BF\u30A4\u30D7ID -OptionsCategory_Name_FileTypeId=\u30D5\u30A1\u30A4\u30EB\u30BF\u30A4\u30D7 -UserDefinedFileTypesManager.loadFileTypes.errorMessage=\u65E2\u5B58\u306E\u30D5\u30A1\u30A4\u30EB\u30BF\u30A4\u30D7\u5B9A\u7FA9\u306E\u8AAD\u307F\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F -UserDefinedFileTypesManager.saveFileTypes.errorMessage=\u30D5\u30A1\u30A4\u30EB\u30BF\u30A4\u30D7\u5B9A\u7FA9\u306E\u4FDD\u5B58\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002 -FileTypeIdGlobalSettingsPanel.JOptionPane.invalidInterestingFilesSetName.message=\u30A2\u30E9\u30FC\u30C8\u3092\u8A2D\u5B9A\u3059\u308B\u306B\u306F\u7591\u308F\u3057\u3044\u30D5\u30A1\u30A4\u30EB\u30BB\u30C3\u30C8\u540D\u304C\u5FC5\u8981\u3067\u3059\u3002 -FileTypeIdGlobalSettingsPanel.offsetComboBox.startItem=\u958B\u59CB -FileTypeIdGlobalSettingsPanel.offsetComboBox.endItem=\u505C\u6B62 -FileTypeIdGlobalSettingsPanel.JOptionPane.invalidOffset.length=\u30AA\u30D5\u30BB\u30C3\u30C8\u306F\u30B7\u30B0\u30CD\u30C1\u30E3\u30B5\u30A4\u30BA\u3088\u308A\u5C0F\u3055\u304F\u3066\u306F\u3044\u3051\u307E\u305B\u3093\u3002 -FileTypeIdGlobalSettingsPanel.jLabel1.text=\u30AB\u30B9\u30BF\u30E0\u30D5\u30A1\u30A4\u30EB\u30BF\u30A4\u30D7 -FileTypeIdGlobalSettingsPanel.jLabel2.text=MIME\u30BF\u30A4\u30D7\uFF1A -FileTypeIdGlobalSettingsPanel.jLabel3.text=Autopsy\u306F\u81EA\u52D5\u7684\u306B\u591A\u304F\u306E\u30D5\u30A1\u30A4\u30EB\u30BF\u30A4\u30D7\u3092\u691C\u77E5\u3067\u304D\u307E\u3059\u3002\u3053\u3053\u306B\u306F\u3042\u306A\u305F\u306E\u30AB\u30B9\u30BF\u30E0\u306E\u30D5\u30A1\u30A4\u30EB\u30BF\u30A4\u30D7\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044\u3002 -FileTypeIdGlobalSettingsPanel.startUp.fileTypeDetectorInitializationException.msg=\u30D5\u30A1\u30A4\u30EB\u30BF\u30A4\u30D7\u30C7\u30A3\u30C6\u30AF\u30BF\u3092\u8D77\u52D5\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002 -FileTypeIdIngestModule.startUp.fileTypeDetectorInitializationException.msg=\u30D5\u30A1\u30A4\u30EB\u30BF\u30A4\u30D7\u30C7\u30A3\u30C6\u30AF\u30BF\u3092\u8D77\u52D5\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002 -FileTypeIdGlobalSettingsPanel.offsetRelativeToLabel.text=\u30AA\u30D5\u30BB\u30C3\u30C8\u306F\u6B21\u3068\u76F8\u5BFE\u7684 +OpenIDE-Module-Name=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7ID +FileTypeIdIngestModule.moduleName.text=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\u306e\u7279\u5b9a +FileTypeIdIngestModule.moduleDesc.text=\u30d0\u30a4\u30ca\u30ea\u30b7\u30b0\u30cd\u30c1\u30e3\u306b\u57fa\u3065\u3044\u3066\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\u3092\u4e00\u81f4\u3057\u307e\u3059\u3002 +FileTypeIdIngestModule.complete.totalProcTime=\u5408\u8a08\u51e6\u7406\u6642\u9593 +FileTypeIdIngestModule.complete.totalFiles=\u5408\u8a08\u51e6\u7406\u30d5\u30a1\u30a4\u30eb\u6570 +FileTypeIdIngestModule.complete.srvMsg.text=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7ID\u306e\u7d50\u679c +FileTypeIdModuleFactory.getIngestJobSettingsPanel.exception.msg=\u8a2d\u5b9a\u3092\u884c\u3046\u70ba\u306e\u60f3\u5b9a\u3055\u308c\u308b\u5f15\u6570\u306finstanceof FileTypeIdModuleSettings\u3067\u3059\u3002 +FileTypeIdModuleFactory.createFileIngestModule.exception.msg=\u8a2d\u5b9a\u3092\u884c\u3046\u70ba\u306e\u60f3\u5b9a\u3055\u308c\u308b\u5f15\u6570\u306finstanceof FileTypeIdModuleSettings\u3067\u3059\u3002 +FileTypeIdIngestJobSettingsPanel.skipKnownCheckBox.toolTipText=\u65e2\u77e5\u306e\u30cf\u30c3\u30b7\u30e5\u5024\u3092\u6301\u3064\u30d5\u30a1\u30a4\u30eb\u6570\u306b\u3088\u3063\u3066\u306f\u3001\u3053\u306e\u30dc\u30c3\u30af\u30b9\u3092\u9078\u629e\u3059\u308b\u3053\u3068\u306b\u3088\u308a\u3001\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\u306e\u7279\u5b9a\u3092\u52a0\u901f\u3057\u307e\u3059\u3002 +FileTypeIdIngestJobSettingsPanel.skipKnownCheckBox.text=\u65e2\u77e5\u30d5\u30a1\u30a4\u30eb\uff08NSRL\uff09\u3092\u30b9\u30ad\u30c3\u30d7 +FileTypeIdGlobalSettingsPanel.deleteTypeButton.text=\u524a\u9664 +FileTypeIdGlobalSettingsPanel.filesSetNameLabel.text=\u30bb\u30c3\u30c8\u540d +FileTypeIdGlobalSettingsPanel.ingestRunningWarningLabel.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3092\u5b9f\u884c\u4e2d\u306b\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\u5b9a\u7fa9\u3092\u5909\u66f4\u3067\u304d\u307e\u305b\u3093\uff01 +FileTypeIdGlobalSettingsPanel.JOptionPane.invalidInterestingFilesSetName.title=\u7591\u308f\u3057\u3044\u30d5\u30a1\u30a4\u30eb\u30bb\u30c3\u30c8\u540d\u304c\u6b20\u3051\u3066\u3044\u307e\u3059 +FileTypeIdGlobalSettingsPanel.JOptionPane.invalidMIMEType.message=MIME\u30bf\u30a4\u30d7\u304c\u5fc5\u8981\u3067\u3059\u3002 +FileTypeIdGlobalSettingsPanel.JOptionPane.invalidMIMEType.title=MIME\u30bf\u30a4\u30d7\u304c\u6b20\u3051\u3066\u3044\u307e\u3059 +FileTypeIdGlobalSettingsPanel.JOptionPane.invalidOffset.message=\u30aa\u30d5\u30bb\u30c3\u30c8\u306f\u6b63\u6574\u6570\u3067\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093\u3002 +FileTypeIdGlobalSettingsPanel.JOptionPane.invalidOffset.title=\u7121\u52b9\u306a\u30aa\u30d5\u30bb\u30c3\u30c8 +FileTypeIdGlobalSettingsPanel.JOptionPane.invalidRawSignatureBytes.message=\u3053\u306e\u30b7\u30b0\u30cd\u30c1\u30e3\u306b\u4e00\u3064\u4ee5\u4e0a\u306e\u7121\u52b9\u306a16\u9032\u6570\u304c\u542b\u307e\u308c\u3066\u3044\u307e\u3059\u3002 +FileTypeIdGlobalSettingsPanel.JOptionPane.invalidSignature.message=\u30b7\u30b0\u30cd\u30c1\u30e3\u304c\u5fc5\u8981\u3067\u3059\u3002 +FileTypeIdGlobalSettingsPanel.JOptionPane.invalidSignature.title=\u30b7\u30b0\u30cd\u30c1\u30e3\u304c\u6b20\u3051\u3066\u3044\u307e\u3059 +FileTypeIdGlobalSettingsPanel.JOptionPane.invalidSignatureBytes.title=\u30b7\u30b0\u30cd\u30c1\u30e3\u304c\u7121\u52b9\u3067\u3059 +FileTypeIdGlobalSettingsPanel.JOptionPane.loadFailed.title=\u8aad\u307f\u8fbc\u307f\u304c\u5931\u6557\u3057\u307e\u3057\u305f +FileTypeIdGlobalSettingsPanel.JOptionPane.storeFailed.title=\u4fdd\u5b58\u304c\u5931\u6557\u3057\u307e\u3057\u305f +FileTypeIdGlobalSettingsPanel.mimeTypeLabel.text=MIME\u30bf\u30a4\u30d7 +FileTypeIdGlobalSettingsPanel.newTypeButton.text=\u65b0\u898f\u30bf\u30a4\u30d7 +FileTypeIdGlobalSettingsPanel.offsetLabel.text=\u30d0\u30a4\u30c8\u30aa\u30d5\u30bb\u30c3\u30c8 +FileTypeIdGlobalSettingsPanel.postHitCheckBox.text=\u767a\u898b\u3057\u305f\u969b\u306b\u300c\u7591\u308f\u3057\u3044\u30d5\u30a1\u30a4\u30eb\u300d\u3068\u8b66\u544a +FileTypeIdGlobalSettingsPanel.saveTypeButton.text=\u4fdd\u5b58\u30bf\u30a4\u30d7 +FileTypeIdGlobalSettingsPanel.signatureComboBox.asciiItem=\u30b9\u30c8\u30ea\u30f3\u30b0\uff08ASCII\uff09 +FileTypeIdGlobalSettingsPanel.signatureComboBox.rawItem=\u30d0\u30a4\u30c8\uff08HEX\uff09 +FileTypeIdGlobalSettingsPanel.signatureLabel.text=\u30b7\u30b0\u30cd\u30c1\u30e3 +FileTypeIdGlobalSettingsPanel.signatureTypeLabel.text=\u30b7\u30b0\u30cd\u30c1\u30e3\u30bf\u30a4\u30d7 +OptionsCategory_Keywords_FileTypeId=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7ID +OptionsCategory_Name_FileTypeId=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7 +UserDefinedFileTypesManager.loadFileTypes.errorMessage=\u65e2\u5b58\u306e\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\u5b9a\u7fa9\u306e\u8aad\u307f\u8fbc\u307f\u306b\u5931\u6557\u3057\u307e\u3057\u305f +UserDefinedFileTypesManager.saveFileTypes.errorMessage=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\u5b9a\u7fa9\u306e\u4fdd\u5b58\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 +FileTypeIdGlobalSettingsPanel.JOptionPane.invalidInterestingFilesSetName.message=\u30a2\u30e9\u30fc\u30c8\u3092\u8a2d\u5b9a\u3059\u308b\u306b\u306f\u7591\u308f\u3057\u3044\u30d5\u30a1\u30a4\u30eb\u30bb\u30c3\u30c8\u540d\u304c\u5fc5\u8981\u3067\u3059\u3002 +FileTypeIdGlobalSettingsPanel.offsetComboBox.startItem=\u958b\u59cb +FileTypeIdGlobalSettingsPanel.offsetComboBox.endItem=\u505c\u6b62 +FileTypeIdGlobalSettingsPanel.JOptionPane.invalidOffset.length=\u30aa\u30d5\u30bb\u30c3\u30c8\u306f\u30b7\u30b0\u30cd\u30c1\u30e3\u30b5\u30a4\u30ba\u3088\u308a\u5c0f\u3055\u304f\u3066\u306f\u3044\u3051\u307e\u305b\u3093\u3002 +FileTypeIdGlobalSettingsPanel.jLabel2.text=MIME\u30bf\u30a4\u30d7\uff1a +FileTypeIdGlobalSettingsPanel.jLabel3.text=Autopsy\u306f\u81ea\u52d5\u7684\u306b\u591a\u304f\u306e\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\u3092\u691c\u77e5\u3067\u304d\u307e\u3059\u3002\u3053\u3053\u306b\u306f\u3042\u306a\u305f\u306e\u30ab\u30b9\u30bf\u30e0\u306e\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +FileTypeIdGlobalSettingsPanel.startUp.fileTypeDetectorInitializationException.msg=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\u30c7\u30a3\u30c6\u30af\u30bf\u3092\u8d77\u52d5\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +FileTypeIdIngestModule.startUp.fileTypeDetectorInitializationException.msg=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\u30c7\u30a3\u30c6\u30af\u30bf\u3092\u8d77\u52d5\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +FileTypeIdGlobalSettingsPanel.offsetRelativeToLabel.text=\u30aa\u30d5\u30bb\u30c3\u30c8\u306f\u6b21\u3068\u76f8\u5bfe\u7684 diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java index 0d82d62731..e6e8269ac9 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2014-2016 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -35,10 +35,10 @@ import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; -import org.sleuthkit.datamodel.TskDataException; /** - * Detects the type of a file by an inspection of its contents. + * Detects the MIME type of a file by an inspection of its contents, using both + * user-defined type definitions and Tika. */ public class FileTypeDetector { @@ -49,11 +49,14 @@ public class FileTypeDetector { private static final Logger logger = Logger.getLogger(FileTypeDetector.class.getName()); /** - * Constructs an object that detects the type of a file by an inspection of - * its contents. + * Constructs an object that detects the MIME type of a file by an + * inspection of its contents, using both user-defined type definitions and + * Tika. * - * @throws FileTypeDetector.FileTypeDetectorInitException if an - * initialization error occurs. + * @throws FileTypeDetectorInitException if an initialization error occurs, + * e.g., user-defined file type + * definitions exist but cannot be + * loaded. */ public FileTypeDetector() throws FileTypeDetectorInitException { try { @@ -63,13 +66,28 @@ public class FileTypeDetector { } } + /** + * Gets the names of the user-defined MIME types. + * + * @return A list of the user-defined MIME types. + */ + public List getUserDefinedTypes() { + List list = new ArrayList<>(); + if (userDefinedFileTypes != null) { + for (FileType fileType : userDefinedFileTypes) { + list.add(fileType.getMimeType()); + } + } + return list; + } + /** * Determines whether or not a given MIME type is detectable by this * detector. * - * @param mimeType The MIME type name, e.g. "text/html", to look up. + * @param mimeType The MIME type name (e.g., "text/html"). * - * @return True if MIME type is detectable. + * @return True or false. */ public boolean isDetectable(String mimeType) { return isDetectableAsUserDefinedType(mimeType) || isDetectableByTika(mimeType); @@ -77,11 +95,11 @@ public class FileTypeDetector { /** * Determines whether or not a given MIME type is detectable as a - * user-defined file type. + * user-defined MIME type by this detector. * - * @param mimeType The MIME type name, e.g. "text/html", to look up. + * @param mimeType The MIME type name (e.g., "text/html"). * - * @return True if MIME type is detectable. + * @return True or false. */ private boolean isDetectableAsUserDefinedType(String mimeType) { for (FileType fileType : userDefinedFileTypes) { @@ -95,9 +113,9 @@ public class FileTypeDetector { /** * Determines whether or not a given MIME type is detectable by Tika. * - * @param mimeType The MIME type name, e.g. "text/html", to look up. + * @param mimeType The MIME type name (e.g., "text/html"). * - * @return True if MIME type is detectable. + * @return True or false. */ private boolean isDetectableByTika(String mimeType) { String[] split = mimeType.split("/"); @@ -112,70 +130,70 @@ public class FileTypeDetector { } /** - * Look up the MIME type of a file using the blackboard. If it is not - * already posted, detect the type of the file, posting it to the blackboard - * if detection succeeds. + * Gets the MIME type of a file, detecting it if it is not already known. If + * detection is necessary, the result is added to the case database. * - * @param file The file to test. + * IMPORTANT: This method should not be called except by ingest modules; all + * other clients should call AbstractFile.getMIMEType, and may call + * FileTypeDetector.detect, if AbstractFile.getMIMEType returns null. * - * @return The MIME type name if detection was successful, null otherwise. + * @param file The file. * - * @throws TskCoreException - */ - public String getFileType(AbstractFile file) throws TskCoreException { - String fileType = file.getMIMEType(); - if (null != fileType) { - return fileType; - } - return detectAndPostToBlackboard(file); - } - - /** - * Detect the MIME type of a file, posting it to the blackboard if detection - * succeeds. Note that this method should currently be called at most once - * per file. + * @return A MIME type name. * - * @param file The file to test. - * - * @return The MIME type name id detection was successful, null otherwise. - * - * @throws TskCoreException + * @throws TskCoreException if detection is required and there is a problem + * writing the result to the case database. */ @SuppressWarnings("deprecation") - public String detectAndPostToBlackboard(AbstractFile file) throws TskCoreException { - String mimeType = detect(file); + public String getFileType(AbstractFile file) throws TskCoreException { + String mimeType = file.getMIMEType(); if (null != mimeType) { - /** - * Add the file type attribute to the general info artifact. Note - * that no property change is fired for this blackboard posting - * because general info artifacts are different from other - * artifacts, e.g., they are not displayed in the results tree. - */ - try { - file.setMIMEType(mimeType); - BlackboardArtifact getInfoArt = file.getGenInfoArtifact(); - BlackboardAttribute batt = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_FILE_TYPE_SIG, FileTypeIdModuleFactory.getModuleName(), mimeType); - getInfoArt.addAttribute(batt); - } catch (TskDataException ex) { - //Swallowing exception so that the logs aren't clogged in the case that ingest is run multiple times. - } + return mimeType; } + + mimeType = detect(file); + Case.getCurrentCase().getSleuthkitCase().setFileMIMEType(file, mimeType); + + /* + * Add the file type attribute to the general info artifact. Note that + * no property change is fired for this blackboard posting because + * general info artifacts are different from other artifacts, e.g., they + * are not displayed in the results tree. + * + * SPECIAL NOTE: Adding a file type attribute to the general info + * artifact is meant to be replaced by the use of the MIME type field of + * the AbstractFile class (tsk_files.mime_type in the case database). + * The attribute is still added here to support backward compatibility, + * but it introduces a check-then-act race condition that can lead to + * duplicate attributes. Various mitigation strategies were considered. + * It was decided to go with the policy that this method would not be + * called outside of ingest (see note in method docs), at least until + * such time as the attribute is no longer created. + */ + BlackboardArtifact getInfoArt = file.getGenInfoArtifact(); + BlackboardAttribute batt = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_FILE_TYPE_SIG, FileTypeIdModuleFactory.getModuleName(), mimeType); + getInfoArt.addAttribute(batt); + return mimeType; } /** - * Detect the MIME type of a file. + * Detects the MIME type of a file. The result is not added to the case + * database. * * @param file The file to test. * - * @return The MIME type name if detection was successful, null otherwise. + * @return A MIME type name. If file type could not be detected or results + * were uncertain, octet-stream is returned. * * @throws TskCoreException */ public String detect(AbstractFile file) throws TskCoreException { - // consistently mark non-regular files (refer TskData.TSK_FS_META_TYPE_ENUM), - // 0 sized files, unallocated, and unused blocks (refer TskData.TSK_DB_FILES_TYPE_ENUM) - // as octet-stream. + /* + * Mark non-regular files (refer to TskData.TSK_FS_META_TYPE_ENUM), + * zero-sized files, unallocated space, and unused blocks (refer to + * TskData.TSK_DB_FILES_TYPE_ENUM) as octet-stream. + */ if (!file.isFile() || file.getSize() <= 0 || (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) || (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) @@ -183,8 +201,15 @@ public class FileTypeDetector { return MimeTypes.OCTET_STREAM; } - String fileType = detectUserDefinedType(file); - if (null == fileType) { + /* + * Give precedence to user-defined types. + */ + String mimeType = detectUserDefinedType(file); + if (null == mimeType) { + /* + * The file does not match a user-defined type. Send the initial + * bytes to Tika. + */ try { byte buf[]; int len = file.read(buffer, 0, BUFFER_SIZE); @@ -194,24 +219,25 @@ public class FileTypeDetector { } else { buf = buffer; } + String tikaType = tika.detect(buf, file.getName()); - String mimetype = tika.detect(buf, file.getName()); - - /** - * Strip out any Tika enhancements to the MIME type name. + /* + * Remove the Tika suffix from the MIME type name. */ - return mimetype.replace("tika-", ""); //NON-NLS + mimeType = tikaType.replace("tika-", ""); //NON-NLS } catch (Exception ignored) { - /** - * This exception is swallowed rather than propagated because - * files in images are not always consistent with their file - * system meta data making for read errors, and Tika can be a - * bit flaky at times, making this a best effort endeavor. + /* + * This exception is swallowed and not logged rather than + * propagated because files in data sources are not always + * consistent with their file system metadata, making for read + * errors. Also, Tika can be a bit flaky at times, making this a + * best effort endeavor. Default to octet-stream. */ + mimeType = MimeTypes.OCTET_STREAM; } } - return fileType; + return mimeType; } /** @@ -230,21 +256,26 @@ public class FileTypeDetector { for (FileType fileType : userDefinedFileTypes) { if (fileType.matches(file)) { if (fileType.alertOnMatch()) { + /* + * Create an interesting file hit artifact. + */ BlackboardArtifact artifact; artifact = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT); BlackboardAttribute setNameAttribute = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, FileTypeIdModuleFactory.getModuleName(), fileType.getFilesSetName()); artifact.addAttribute(setNameAttribute); - /** - * Use the MIME type as the category, i.e., the rule that - * determined this file belongs to the interesting files - * set. + /* + * Use the MIME type as the category attribute, i.e., the + * rule that determined this file belongs to the interesting + * files set. */ BlackboardAttribute ruleNameAttribute = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY, FileTypeIdModuleFactory.getModuleName(), fileType.getMimeType()); artifact.addAttribute(ruleNameAttribute); + /* + * Index the artifact for keyword search. + */ try { - // index the artifact for keyword search Case.getCurrentCase().getServices().getBlackboard().indexArtifact(artifact); } catch (Blackboard.BlackboardException | IllegalStateException ex) { logger.log(Level.SEVERE, String.format("Unable to index blackboard artifact %d", artifact.getArtifactID()), ex); //NON-NLS @@ -258,30 +289,54 @@ public class FileTypeDetector { return null; } + /* + * Exception thrown when a file type detector experiences an error + * condition. + */ public static class FileTypeDetectorInitException extends Exception { + private static final long serialVersionUID = 1L; + /** + * Constructs an exception to throw when a file type detector + * experiences an error condition. + * + * @param message The exception message, + */ FileTypeDetectorInitException(String message) { super(message); } + /** + * Constructs an exception to throw when a file type detector + * experiences an error condition. + * + * @param message The exception message, + * @param throwable The underlying cause of the exception. + */ FileTypeDetectorInitException(String message, Throwable throwable) { super(message, throwable); } + } /** - * Gets the list of user defined file types (MIME types) + * Gets the MIME type of a file, detecting it if it is not already known. If + * detection is necessary, the result is added to the case database. * - * @return the List of user defined file types + * @param file The file. + * + * @return A MIME type name. + * + * @throws TskCoreException if detection is required and there is a problem + * writing the result to the case database. + * @deprecated Use getFileType instead and use AbstractFile.getMIMEType + * instead of querying the blackboard. */ - public List getUserDefinedTypes() { - List list = new ArrayList<>(); - if (userDefinedFileTypes != null) { - for (FileType fileType : userDefinedFileTypes) { - list.add(fileType.getMimeType()); - } - } - return list; + @Deprecated + @SuppressWarnings("deprecation") + public String detectAndPostToBlackboard(AbstractFile file) throws TskCoreException { + return getFileType(file); } + } diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.form b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.form index 91181f984d..7e8b342a16 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.form @@ -95,10 +95,9 @@ - - + @@ -107,7 +106,6 @@ - @@ -167,7 +165,7 @@ - + @@ -426,18 +424,6 @@ - - - - - - - - - - - - diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.java index ef174b3155..ee5e9720bf 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdGlobalSettingsPanel.java @@ -84,7 +84,9 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane * Does child component initialization in addition to that done by the * Matisse generated code. */ + @NbBundle.Messages({"FileTypeIdGlobalSettingsPanel.Title=Global File Type Identification Settings"}) private void customizeComponents() { + setName(Bundle.FileTypeIdGlobalSettingsPanel_Title()); setFileTypesListModel(); setSignatureTypeComboBoxModel(); setOffsetRealtiveToComboBoxModel(); @@ -352,7 +354,7 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane private void initComponents() { typesScrollPane = new javax.swing.JScrollPane(); - typesList = new javax.swing.JList<>(); + typesList = new javax.swing.JList(); separator = new javax.swing.JSeparator(); mimeTypeLabel = new javax.swing.JLabel(); mimeTypeTextField = new javax.swing.JTextField(); @@ -364,16 +366,15 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane deleteTypeButton = new javax.swing.JButton(); saveTypeButton = new javax.swing.JButton(); hexPrefixLabel = new javax.swing.JLabel(); - signatureTypeComboBox = new javax.swing.JComboBox<>(); + signatureTypeComboBox = new javax.swing.JComboBox(); signatureLabel = new javax.swing.JLabel(); postHitCheckBox = new javax.swing.JCheckBox(); filesSetNameLabel = new javax.swing.JLabel(); filesSetNameTextField = new javax.swing.JTextField(); ingestRunningWarningLabel = new javax.swing.JLabel(); - jLabel1 = new javax.swing.JLabel(); jLabel2 = new javax.swing.JLabel(); jLabel3 = new javax.swing.JLabel(); - offsetRelativeToComboBox = new javax.swing.JComboBox<>(); + offsetRelativeToComboBox = new javax.swing.JComboBox(); offsetRelativeToLabel = new javax.swing.JLabel(); setMaximumSize(new java.awt.Dimension(500, 300)); @@ -464,9 +465,6 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane ingestRunningWarningLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/modules/filetypeid/warning16.png"))); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(ingestRunningWarningLabel, org.openide.util.NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.ingestRunningWarningLabel.text")); // NOI18N - jLabel1.setFont(jLabel1.getFont().deriveFont(jLabel1.getFont().getStyle() | java.awt.Font.BOLD, 11)); - org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.jLabel1.text")); // NOI18N - jLabel2.setFont(jLabel2.getFont().deriveFont(jLabel2.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.jLabel2.text")); // NOI18N @@ -538,15 +536,13 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane .addComponent(offsetRelativeToLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(offsetRelativeToComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))) - .addComponent(jLabel1) .addComponent(jLabel3)) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))) + .addContainerGap(28, Short.MAX_VALUE)))) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addComponent(jLabel1) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addContainerGap() .addComponent(jLabel3) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -594,7 +590,7 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane .addComponent(filesSetNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(saveTypeButton) - .addGap(0, 0, Short.MAX_VALUE)))) + .addGap(0, 21, Short.MAX_VALUE)))) ); layout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {deleteTypeButton, newTypeButton, saveTypeButton}); @@ -735,7 +731,6 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane private javax.swing.JTextField filesSetNameTextField; private javax.swing.JLabel hexPrefixLabel; private javax.swing.JLabel ingestRunningWarningLabel; - private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel2; private javax.swing.JLabel jLabel3; private javax.swing.JLabel mimeTypeLabel; diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdIngestJobSettingsPanel.form b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdIngestJobSettingsPanel.form deleted file mode 100644 index 183425da42..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdIngestJobSettingsPanel.form +++ /dev/null @@ -1,52 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdIngestJobSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdIngestJobSettingsPanel.java deleted file mode 100644 index 658e0c00b9..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdIngestJobSettingsPanel.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2013 - 2014 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sleuthkit.autopsy.modules.filetypeid; - -import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; -import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel; - -/** - * UI component used to set ingest job options for file type identifier ingest - * modules. - */ -class FileTypeIdIngestJobSettingsPanel extends IngestModuleIngestJobSettingsPanel { - - private final FileTypeIdModuleSettings settings; - - FileTypeIdIngestJobSettingsPanel(FileTypeIdModuleSettings settings) { - this.settings = settings; - initComponents(); - customizeComponents(); - } - - /** - * @inheritDoc - */ - @Override - public IngestModuleIngestJobSettings getSettings() { - return settings; - } - - /** - * Does child component initialization in addition to that done by the - * Matisse generated code. - */ - private void customizeComponents() { - skipKnownCheckBox.setSelected(settings.skipKnownFiles()); - } - - /** - * 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") - // //GEN-BEGIN:initComponents - private void initComponents() { - - skipKnownCheckBox = new javax.swing.JCheckBox(); - - skipKnownCheckBox.setSelected(true); - skipKnownCheckBox.setText(org.openide.util.NbBundle.getMessage(FileTypeIdIngestJobSettingsPanel.class, "FileTypeIdIngestJobSettingsPanel.skipKnownCheckBox.text")); // NOI18N - skipKnownCheckBox.setToolTipText(org.openide.util.NbBundle.getMessage(FileTypeIdIngestJobSettingsPanel.class, "FileTypeIdIngestJobSettingsPanel.skipKnownCheckBox.toolTipText")); // NOI18N - skipKnownCheckBox.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - skipKnownCheckBoxActionPerformed(evt); - } - }); - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); - this.setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addGap(10, 10, 10) - .addComponent(skipKnownCheckBox) - .addContainerGap(46, Short.MAX_VALUE)) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addGap(11, 11, 11) - .addComponent(skipKnownCheckBox) - .addContainerGap(86, Short.MAX_VALUE)) - ); - }// //GEN-END:initComponents - - private void skipKnownCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_skipKnownCheckBoxActionPerformed - settings.setSkipKnownFiles(skipKnownCheckBox.isSelected()); - }//GEN-LAST:event_skipKnownCheckBoxActionPerformed - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JCheckBox skipKnownCheckBox; - // End of variables declaration//GEN-END:variables -} diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdIngestModule.java index b3c09dfb81..3e6e35e8ae 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdIngestModule.java @@ -27,7 +27,6 @@ import org.sleuthkit.autopsy.ingest.IngestJobContext; import org.sleuthkit.autopsy.ingest.IngestMessage; import org.sleuthkit.autopsy.ingest.IngestServices; import org.sleuthkit.datamodel.AbstractFile; -import org.sleuthkit.datamodel.TskData.FileKnown; import org.sleuthkit.autopsy.ingest.IngestModule.ProcessResult; import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter; @@ -38,7 +37,6 @@ import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter; public class FileTypeIdIngestModule implements FileIngestModule { private static final Logger logger = Logger.getLogger(FileTypeIdIngestModule.class.getName()); - private final FileTypeIdModuleSettings settings; private long jobId; private static final HashMap totalsForIngestJobs = new HashMap<>(); private static final IngestModuleReferenceCounter refCounter = new IngestModuleReferenceCounter(); @@ -66,11 +64,8 @@ public class FileTypeIdIngestModule implements FileIngestModule { /** * Creates an ingest module that detects the type of a file based on * signature (magic) values. Posts results to the blackboard. - * - * @param settings The ingest module settings. */ - FileTypeIdIngestModule(FileTypeIdModuleSettings settings) { - this.settings = settings; + FileTypeIdIngestModule() { } /** @@ -83,7 +78,7 @@ public class FileTypeIdIngestModule implements FileIngestModule { try { fileTypeDetector = new FileTypeDetector(); } catch (FileTypeDetector.FileTypeDetectorInitException ex) { - throw new IngestModuleException(NbBundle.getMessage(this.getClass(), "FileTypeIdIngestModule.startUp.fileTypeDetectorInitializationException.msg")); + throw new IngestModuleException(NbBundle.getMessage(this.getClass(), "FileTypeIdIngestModule.startUp.fileTypeDetectorInitializationException.msg"), ex); } } @@ -93,13 +88,6 @@ public class FileTypeIdIngestModule implements FileIngestModule { @Override public ProcessResult process(AbstractFile file) { - /** - * Skip known files if configured to do so. - */ - if (settings.skipKnownFiles() && (file.getKnown() == FileKnown.KNOWN)) { - return ProcessResult.OK; - } - /** * Attempt to detect the file type. Do it within an exception firewall, * so that any issues with reading file content or complaints from tika @@ -153,7 +141,7 @@ public class FileTypeIdIngestModule implements FileIngestModule { * Update the match time total and increment number of files processed for * this ingest job. * - * @param jobId The ingest job identifier. + * @param jobId The ingest job identifier. * @param matchTimeInc Amount of time to add. */ private static synchronized void addToTotals(long jobId, long matchTimeInc) { diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdModuleFactory.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdModuleFactory.java index 38823ca03d..78ccd986a0 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdModuleFactory.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdModuleFactory.java @@ -26,7 +26,6 @@ import org.sleuthkit.autopsy.ingest.IngestModuleFactory; import org.sleuthkit.autopsy.ingest.IngestModuleFactoryAdapter; import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSettingsPanel; import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; -import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel; /** * A factory that creates file ingest modules that determine the types of files. @@ -92,35 +91,6 @@ public class FileTypeIdModuleFactory extends IngestModuleFactoryAdapter { return globalSettingsPanel; } - /** - * @inheritDoc - */ - @Override - public IngestModuleIngestJobSettings getDefaultIngestJobSettings() { - return new FileTypeIdModuleSettings(); - } - - /** - * @inheritDoc - */ - @Override - public boolean hasIngestJobSettingsPanel() { - return true; - } - - /** - * @inheritDoc - */ - @Override - public IngestModuleIngestJobSettingsPanel getIngestJobSettingsPanel(IngestModuleIngestJobSettings settings) { - assert settings instanceof FileTypeIdModuleSettings; - if (!(settings instanceof FileTypeIdModuleSettings)) { - throw new IllegalArgumentException(NbBundle.getMessage(this.getClass(), - "FileTypeIdModuleFactory.getIngestJobSettingsPanel.exception.msg")); - } - return new FileTypeIdIngestJobSettingsPanel((FileTypeIdModuleSettings) settings); - } - /** * @inheritDoc */ @@ -134,11 +104,6 @@ public class FileTypeIdModuleFactory extends IngestModuleFactoryAdapter { */ @Override public FileIngestModule createFileIngestModule(IngestModuleIngestJobSettings settings) { - assert settings instanceof FileTypeIdModuleSettings; - if (!(settings instanceof FileTypeIdModuleSettings)) { - throw new IllegalArgumentException( - NbBundle.getMessage(this.getClass(), "FileTypeIdModuleFactory.createFileIngestModule.exception.msg")); - } - return new FileTypeIdIngestModule((FileTypeIdModuleSettings) settings); + return new FileTypeIdIngestModule(); } -} +} \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdModuleSettings.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdModuleSettings.java deleted file mode 100755 index 8d8e4150d5..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdModuleSettings.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2014 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sleuthkit.autopsy.modules.filetypeid; - -import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; - -/** - * Ingest job options for the file type identifier ingest module instances. - */ -// TODO: This class does not need to be public. -public class FileTypeIdModuleSettings implements IngestModuleIngestJobSettings { - - private static final long serialVersionUID = 1L; - private boolean skipKnownFiles = true; - private boolean skipSmallFiles = false; // No longer used. - - FileTypeIdModuleSettings() { - } - - FileTypeIdModuleSettings(boolean skipKnownFiles) { - this.skipKnownFiles = skipKnownFiles; - } - - /** - * @inheritDoc - */ - @Override - public long getVersionNumber() { - return serialVersionUID; - } - - void setSkipKnownFiles(boolean enabled) { - skipKnownFiles = enabled; - } - - boolean skipKnownFiles() { - return skipKnownFiles; - } - -} diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java index 5dd48f58f2..8f2dbaabca 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/UserDefinedFileTypesManager.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2014 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -59,7 +59,6 @@ import org.xml.sax.SAXException; final class UserDefinedFileTypesManager { private static final Logger logger = Logger.getLogger(UserDefinedFileTypesManager.class.getName()); - private static final String FILE_TYPE_DEFINITIONS_SCHEMA_FILE = "FileTypes.xsd"; //NON-NLS private static final String USER_DEFINED_TYPE_DEFINITIONS_FILE = "UserFileTypeDefinitions.xml"; //NON-NLS private static final String FILE_TYPES_TAG_NAME = "FileTypes"; //NON-NLS private static final String FILE_TYPE_TAG_NAME = "FileType"; //NON-NLS @@ -72,7 +71,6 @@ final class UserDefinedFileTypesManager { private static final String INTERESTING_FILES_SET_TAG_NAME = "InterestingFileSset"; //NON-NLS private static final String ALERT_ATTRIBUTE = "alert"; //NON-NLS private static final String ENCODING_FOR_XML_FILE = "UTF-8"; //NON-NLS - private static final String ASCII_ENCODING = "US-ASCII"; //NON-NLS private static UserDefinedFileTypesManager instance; /** @@ -181,7 +179,7 @@ final class UserDefinedFileTypesManager { private void loadPredefinedFileTypes() throws UserDefinedFileTypesException { byte[] byteArray; FileType fileType; - + try { // Add rule for xml fileType = new FileType("text/xml", new Signature(" newFileTypes) throws UserDefinedFileTypesException { try { @@ -317,7 +314,7 @@ final class UserDefinedFileTypesManager { * Writes a set of file type definitions to an XML file. * * @param fileTypes A collection of file types. - * @param filePath The path to the destination file. + * @param filePath The path to the destination file. * * @throws ParserConfigurationException * @throws IOException @@ -340,7 +337,7 @@ final class UserDefinedFileTypesManager { * Creates an XML representation of a file type. * * @param fileType The file type object. - * @param doc The WC3 DOM object to use to create the XML. + * @param doc The WC3 DOM object to use to create the XML. * * @return An XML element. */ @@ -356,9 +353,9 @@ final class UserDefinedFileTypesManager { /** * Add a MIME type child element to a file type XML element. * - * @param fileType The file type to use as a content source. + * @param fileType The file type to use as a content source. * @param fileTypeElem The parent file type element. - * @param doc The WC3 DOM object to use to create the XML. + * @param doc The WC3 DOM object to use to create the XML. */ private static void addMimeTypeElement(FileType fileType, Element fileTypeElem, Document doc) { Element typeNameElem = doc.createElement(MIME_TYPE_TAG_NAME); @@ -369,9 +366,9 @@ final class UserDefinedFileTypesManager { /** * Add a signature child element to a file type XML element. * - * @param fileType The file type to use as a content source. + * @param fileType The file type to use as a content source. * @param fileTypeElem The parent file type element. - * @param doc The WC3 DOM object to use to create the XML. + * @param doc The WC3 DOM object to use to create the XML. */ private static void addSignatureElement(FileType fileType, Element fileTypeElem, Document doc) { Signature signature = fileType.getSignature(); @@ -393,9 +390,9 @@ final class UserDefinedFileTypesManager { /** * Add an interesting files set element to a file type XML element. * - * @param fileType The file type to use as a content source. + * @param fileType The file type to use as a content source. * @param fileTypeElem The parent file type element. - * @param doc The WC3 DOM object to use to create the XML. + * @param doc The WC3 DOM object to use to create the XML. */ private static void addInterestingFilesSetElement(FileType fileType, Element fileTypeElem, Document doc) { if (!fileType.getFilesSetName().isEmpty()) { @@ -408,13 +405,20 @@ final class UserDefinedFileTypesManager { /** * Add an alert attribute to a file type XML element. * - * @param fileType The file type to use as a content source. + * @param fileType The file type to use as a content source. * @param fileTypeElem The parent file type element. */ private static void addAlertAttribute(FileType fileType, Element fileTypeElem) { fileTypeElem.setAttribute(ALERT_ATTRIBUTE, Boolean.toString(fileType.alertOnMatch())); } + /** + * Private constructor suppresses creation of instanmces of this utility + * class. + */ + private XmlWriter() { + } + } /** @@ -432,7 +436,17 @@ final class UserDefinedFileTypesManager { */ private static List readFileTypes(String filePath) throws IOException, ParserConfigurationException, SAXException { List fileTypes = new ArrayList<>(); - Document doc = XMLUtil.loadDocument(filePath, UserDefinedFileTypesManager.class, FILE_TYPE_DEFINITIONS_SCHEMA_FILE); + /* + * RC: Commenting out the loadDocument overload that validates + * against the XSD is a temp fix for a failure to provide an upgrade + * path when the RelativeToStart attribute was added to the + * Signature element. The upgrade path can be supplied, but the plan + * is to replace the use of XML with object serialization for the + * settings, so it may not be worth the effort. + */ + // private static final String FILE_TYPE_DEFINITIONS_SCHEMA_FILE = "FileTypes.xsd"; //NON-NLS + // Document doc = XMLUtil.loadDocument(filePath, UserDefinedFileTypesManager.class, FILE_TYPE_DEFINITIONS_SCHEMA_FILE); + Document doc = XMLUtil.loadDocument(filePath); if (doc != null) { Element fileTypesElem = doc.getDocumentElement(); if (fileTypesElem != null && fileTypesElem.getNodeName().equals(FILE_TYPES_TAG_NAME)) { @@ -496,14 +510,16 @@ final class UserDefinedFileTypesManager { Element offsetElem = (Element) signatureElem.getElementsByTagName(OFFSET_TAG_NAME).item(0); String offsetString = offsetElem.getTextContent(); long offset = DatatypeConverter.parseLong(offsetString); - - String relativeString = offsetElem.getAttribute(RELATIVE_ATTRIBUTE); - if(relativeString == null || relativeString.equals("")) - return new Signature(signatureBytes, offset, signatureType); - - boolean isRelative = DatatypeConverter.parseBoolean(relativeString); - return new Signature(signatureBytes, offset, signatureType, isRelative); + boolean isRelativeToStart; + String relativeString = offsetElem.getAttribute(RELATIVE_ATTRIBUTE); + if (null == relativeString || relativeString.equals("")) { + isRelativeToStart = true; + } else { + isRelativeToStart = DatatypeConverter.parseBoolean(relativeString); + } + + return new Signature(signatureBytes, offset, signatureType, isRelativeToStart); } /** @@ -538,7 +554,7 @@ final class UserDefinedFileTypesManager { /** * Gets the text content of a single child element. * - * @param elem The parent element. + * @param elem The parent element. * @param tagName The tag name of the child element. * * @return The text content or null if the tag doesn't exist. @@ -546,21 +562,29 @@ final class UserDefinedFileTypesManager { private static String getChildElementTextContent(Element elem, String tagName) { NodeList childElems = elem.getElementsByTagName(tagName); Node childNode = childElems.item(0); - if(childNode == null) + if (childNode == null) { return null; + } Element childElem = (Element) childNode; return childElem.getTextContent(); } + /** + * Private constructor suppresses creation of instanmces of this utility + * class. + */ + private XmlReader() { + } + } /** * Logs an exception, bundles the exception with a simple message in a * uniform exception type, and throws the wrapper exception. * - * @param ex The exception to wrap. + * @param ex The exception to wrap. * @param messageKey A key into the bundle file that maps to the desired - * message. + * message. * * @throws * org.sleuthkit.autopsy.modules.filetypeid.UserDefinedFileTypesManager.UserDefinedFileTypesException @@ -578,6 +602,8 @@ final class UserDefinedFileTypesManager { */ static class UserDefinedFileTypesException extends Exception { + private static final long serialVersionUID = 1L; + UserDefinedFileTypesException(String message) { super(message); } diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties index 6143caecc7..9a43e5cd1a 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties @@ -56,7 +56,6 @@ HashDatabaseOptionsPanelController.moduleErrMsg=A module caused an error listeni HashDbConfigPanel.noSelectionText=No database selected HashDbConfigPanel.errorGettingPathText=Error occurred getting path HashDbConfigPanel.errorGettingIndexStatusText=Error occurred getting status -HashDbConfigPanel.setName.hashSetConfig=Hash Set Configuration HashDbConfigPanel.indexButtonText.index=Index HashDbConfigPanel.indexButtonText.indexing=Indexing HashDbConfigPanel.indexStatusText.indexGen=Index is currently being generated diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle_ja.properties index b53420e4ee..bc5324fdf9 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle_ja.properties @@ -1,213 +1,212 @@ -OpenIDE-Module-Display-Category=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB +OpenIDE-Module-Display-Category=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb OpenIDE-Module-Long-Description=\ - \u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306E\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB \n\n\ - \u30C7\u30A3\u30B9\u30AF\u30A4\u30E1\u30FC\u30B8\u306B\u3042\u308B\u30D5\u30A1\u30A4\u30EB\u3092\u89E3\u6790\u3057\u3001\u300C\u65E2\u77E5\u300D\uFF08NSRL\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306E\u300C\u65E2\u77E5\u300D\u30D5\u30A1\u30A4\u30EB\u30EB\u30C3\u30AF\u30A2\u30C3\u30D7\u3092\u57FA\u306B\uFF09\u307E\u305F\u306F\u300C\u60AA\u8CEA\uFF0F\u7591\u308F\u3057\u3044\u300D\uFF08\u30E6\u30FC\u30B6\u30FC\u304C\u6307\u5B9A\u3057\u305F\u5358\u6570\u307E\u305F\u306F\u8907\u6570\u306E\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u57FA\u306B\uFF09\u3068\u30DE\u30FC\u30AF\u3057\u307E\u3059\u3002\n\n\ - \u30CF\u30C3\u30B7\u30E5\u3084\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u8A2D\u5B9A\u306B\u57FA\u3065\u3044\u305F\u30D5\u30A1\u30A4\u30EB\u30EB\u30C3\u30AF\u30A2\u30C3\u30D7\u306A\u3069\u3001\u3053\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u306FGUI\u306B\u9023\u643A\u3057\u3066\u3044\u308B\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u3057\u306A\u3044\u3001\u8FFD\u52A0\u306E\u30C4\u30FC\u30EB\u304C\u542B\u307E\u308C\u307E\u3059\u3002 -OpenIDE-Module-Name=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9 -HashDbSearchPanel.hashTable.columnModel.title0=MD5\u30CF\u30C3\u30B7\u30E5 -HashDbSearchPanel.addButton.text=\u30CF\u30C3\u30B7\u30E5\u3092\u8FFD\u52A0 -HashDbSearchPanel.hashLabel.text=MD5\u30CF\u30C3\u30B7\u30E5\uFF1A -HashDbSearchPanel.searchButton.text=\u691C\u7D22 -HashDbSearchPanel.removeButton.text=\u9078\u629E\u3057\u305F\u3082\u306E\u3092\u524A\u9664 -HashDbSearchPanel.titleLabel.text=\u6B21\u306EMD5\u30CF\u30C3\u30B7\u30E5\u4ED8\u304D\u306E\u30D5\u30A1\u30A4\u30EB\u3092\u691C\u7D22\uFF1A -HashDbSearchPanel.errorField.text=\u30A8\u30E9\u30FC\uFF1A\u5168\u3066\u306E\u30D5\u30A1\u30A4\u30EB\u304C\u30CF\u30C3\u30B7\u30E5\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F\u3002 -HashDbSearchPanel.saveBox.text=\u30CF\u30C3\u30B7\u30E5\u3092\u8A18\u61B6 -HashDbSearchPanel.cancelButton.text=\u30AD\u30E3\u30F3\u30BB\u30EB -OpenIDE-Module-Short-Description=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306E\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u304A\u3088\u3073\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30C4\u30FC\u30EB -HashDbImportDatabaseDialog.jLabel1.text=\u30CF\u30C3\u30B7\u30E5\u30BB\u30C3\u30C8\u540D\uFF1A -HashDbImportDatabaseDialog.knownBadRadioButton.text=\u65E2\u77E5\u306E\u60AA\u8CEA -HashDbImportDatabaseDialog.jLabel2.text=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306E\u30BF\u30A4\u30D7\uFF1A + \u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb \n\n\ + \u30c7\u30a3\u30b9\u30af\u30a4\u30e1\u30fc\u30b8\u306b\u3042\u308b\u30d5\u30a1\u30a4\u30eb\u3092\u89e3\u6790\u3057\u3001\u300c\u65e2\u77e5\u300d\uff08NSRL\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u300c\u65e2\u77e5\u300d\u30d5\u30a1\u30a4\u30eb\u30eb\u30c3\u30af\u30a2\u30c3\u30d7\u3092\u57fa\u306b\uff09\u307e\u305f\u306f\u300c\u60aa\u8cea\uff0f\u7591\u308f\u3057\u3044\u300d\uff08\u30e6\u30fc\u30b6\u30fc\u304c\u6307\u5b9a\u3057\u305f\u5358\u6570\u307e\u305f\u306f\u8907\u6570\u306e\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u57fa\u306b\uff09\u3068\u30de\u30fc\u30af\u3057\u307e\u3059\u3002\n\n\ + \u30cf\u30c3\u30b7\u30e5\u3084\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u8a2d\u5b9a\u306b\u57fa\u3065\u3044\u305f\u30d5\u30a1\u30a4\u30eb\u30eb\u30c3\u30af\u30a2\u30c3\u30d7\u306a\u3069\u3001\u3053\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u306fGUI\u306b\u9023\u643a\u3057\u3066\u3044\u308b\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3057\u306a\u3044\u3001\u8ffd\u52a0\u306e\u30c4\u30fc\u30eb\u304c\u542b\u307e\u308c\u307e\u3059\u3002 +OpenIDE-Module-Name=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9 +HashDbSearchPanel.hashTable.columnModel.title0=MD5\u30cf\u30c3\u30b7\u30e5 +HashDbSearchPanel.addButton.text=\u30cf\u30c3\u30b7\u30e5\u3092\u8ffd\u52a0 +HashDbSearchPanel.hashLabel.text=MD5\u30cf\u30c3\u30b7\u30e5\uff1a +HashDbSearchPanel.searchButton.text=\u691c\u7d22 +HashDbSearchPanel.removeButton.text=\u9078\u629e\u3057\u305f\u3082\u306e\u3092\u524a\u9664 +HashDbSearchPanel.titleLabel.text=\u6b21\u306eMD5\u30cf\u30c3\u30b7\u30e5\u4ed8\u304d\u306e\u30d5\u30a1\u30a4\u30eb\u3092\u691c\u7d22\uff1a +HashDbSearchPanel.errorField.text=\u30a8\u30e9\u30fc\uff1a\u5168\u3066\u306e\u30d5\u30a1\u30a4\u30eb\u304c\u30cf\u30c3\u30b7\u30e5\u3055\u308c\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +HashDbSearchPanel.saveBox.text=\u30cf\u30c3\u30b7\u30e5\u3092\u8a18\u61b6 +HashDbSearchPanel.cancelButton.text=\u30ad\u30e3\u30f3\u30bb\u30eb +OpenIDE-Module-Short-Description=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u304a\u3088\u3073\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30c4\u30fc\u30eb +HashDbImportDatabaseDialog.jLabel1.text=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u540d\uff1a +HashDbImportDatabaseDialog.knownBadRadioButton.text=\u65e2\u77e5\u306e\u60aa\u8cea +HashDbImportDatabaseDialog.jLabel2.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30bf\u30a4\u30d7\uff1a HashDbImportDatabaseDialog.okButton.text=OK -HashDbImportDatabaseDialog.cancelButton.text=\u30AD\u30E3\u30F3\u30BB\u30EB -HashDbCreateDatabaseDialog.jLabel2.text=\u30BF\u30A4\u30D7\uFF1A -HashDbCreateDatabaseDialog.knownBadRadioButton.text=\u65E2\u77E5\u306E\u60AA\u8CEA -HashDbCreateDatabaseDialog.cancelButton.text=\u30AD\u30E3\u30F3\u30BB\u30EB -ModalNoButtons.CURRENTLYON_LABEL.text=y\u306Ex\u3092\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u4E2D -ModalNoButtons.GO_GET_COFFEE_LABEL.text=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u4E2D\u3067\u3059\u3002\u6642\u9593\u304C\u304B\u304B\u308B\u5834\u5408\u304C\u3042\u308A\u307E\u3059\u3002 -ModalNoButtons.CANCEL_BUTTON.text=\u30AD\u30E3\u30F3\u30BB\u30EB -HashDbImportDatabaseDialog.knownRadioButton.text=\u65E2\u77E5\uFF08NSRL\u307E\u305F\u306F\u305D\u306E\u4ED6\uFF09 -HashDbCreateDatabaseDialog.knownRadioButton.text=\u65E2\u77E5 -HashDbCreateDatabaseDialog.jLabel1.text=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30D1\u30B9\uFF1A -HashDbCreateDatabaseDialog.saveAsButton.text=\u540D\u524D\u3092\u3064\u3051\u3066\u4FDD\u5B58\u2026 -HashDbImportDatabaseDialog.jLabel3.text=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30D1\u30B9\uFF1A -HashDbCreateDatabaseDialog.sendIngestMessagesCheckbox.text=\u30D2\u30C3\u30C8\u6BCE\u306B\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30A4\u30F3\u30DC\u30C3\u30AF\u30B9\u306B\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u9001\u308B -HashDbImportDatabaseDialog.sendIngestMessagesCheckbox.text=\u30D2\u30C3\u30C8\u6BCE\u306B\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30A4\u30F3\u30DC\u30C3\u30AF\u30B9\u306B\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u9001\u308B -HashDbImportDatabaseDialog.openButton.text=\u958B\u304F... -HashDbCreateDatabaseDialog.jLabel3.text=\u30CF\u30C3\u30B7\u30E5\u30BB\u30C3\u30C8\u540D\uFF1A +HashDbImportDatabaseDialog.cancelButton.text=\u30ad\u30e3\u30f3\u30bb\u30eb +HashDbCreateDatabaseDialog.jLabel2.text=\u30bf\u30a4\u30d7\uff1a +HashDbCreateDatabaseDialog.knownBadRadioButton.text=\u65e2\u77e5\u306e\u60aa\u8cea +HashDbCreateDatabaseDialog.cancelButton.text=\u30ad\u30e3\u30f3\u30bb\u30eb +ModalNoButtons.CURRENTLYON_LABEL.text=y\u306ex\u3092\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u4e2d +ModalNoButtons.GO_GET_COFFEE_LABEL.text=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u4e2d\u3067\u3059\u3002\u6642\u9593\u304c\u304b\u304b\u308b\u5834\u5408\u304c\u3042\u308a\u307e\u3059\u3002 +ModalNoButtons.CANCEL_BUTTON.text=\u30ad\u30e3\u30f3\u30bb\u30eb +HashDbImportDatabaseDialog.knownRadioButton.text=\u65e2\u77e5\uff08NSRL\u307e\u305f\u306f\u305d\u306e\u4ed6\uff09 +HashDbCreateDatabaseDialog.knownRadioButton.text=\u65e2\u77e5 +HashDbCreateDatabaseDialog.jLabel1.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30d1\u30b9\uff1a +HashDbCreateDatabaseDialog.saveAsButton.text=\u540d\u524d\u3092\u3064\u3051\u3066\u4fdd\u5b58\u2026 +HashDbImportDatabaseDialog.jLabel3.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30d1\u30b9\uff1a +HashDbCreateDatabaseDialog.sendIngestMessagesCheckbox.text=\u30d2\u30c3\u30c8\u6bce\u306b\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30a4\u30f3\u30dc\u30c3\u30af\u30b9\u306b\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u9001\u308b +HashDbImportDatabaseDialog.sendIngestMessagesCheckbox.text=\u30d2\u30c3\u30c8\u6bce\u306b\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30a4\u30f3\u30dc\u30c3\u30af\u30b9\u306b\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u9001\u308b +HashDbImportDatabaseDialog.openButton.text=\u958b\u304f... +HashDbCreateDatabaseDialog.jLabel3.text=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u540d\uff1a HashDbCreateDatabaseDialog.okButton.text=OK -AddContentToHashDbAction.ContentMenu.noHashDbsConfigd=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093 -AddContentToHashDbAction.ContentMenu.createDbItem=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u4F5C\u6210... -AddContentToHashDbAction.addFilesToHashSet.addToHashDbErr1.text=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30A8\u30E9\u30FC\u306B\u8FFD\u52A0 -AddContentToHashDbAction.addFilesToHashSet.addToHashDbErr2.text=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30A8\u30E9\u30FC\u306B\u8FFD\u52A0 -AddContentToHashDbAction.addFilesToHashSet.addToHashDbErr3.text=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30A8\u30E9\u30FC\u306B\u8FFD\u52A0 -AddContentToHashDbAction.addFilesToHashSet.unableToAddFileMsg=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306B{0}\u3092\u8FFD\u52A0\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002 -AddContentToHashDbAction.addFilesToHashSet.unableToAddFileSzMsg=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306B{0}\u3092\u8FFD\u52A0\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u30CF\u30C3\u30B7\u30E5\u304C\u8A08\u7B97\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002\u9069\u5207\u306A\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u8A2D\u5B9A\u3057\u3001\u5B9F\u884C\u3057\u3066\u4E0B\u3055\u3044\u3002 -HashDatabaseOptionsPanelController.moduleErr=\u30E2\u30B8\u30E5\u30FC\u30EB\u30A8\u30E9\u30FC -HashDatabaseOptionsPanelController.moduleErrMsg=HashDatabaseOptionsPanelController\u306E\u30A2\u30C3\u30D7\u30C7\u30FC\u30C8\u3092\u78BA\u8A8D\u4E2D\u306B\u30E2\u30B8\u30E5\u30FC\u30EB\u304C\u30A8\u30E9\u30FC\u3092\u8D77\u3053\u3057\u307E\u3057\u305F\u3002\u3069\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u304B\u30ED\u30B0\u3092\u78BA\u8A8D\u3057\u3066\u4E0B\u3055\u3044\u3002\u4E00\u90E8\u306E\u30C7\u30FC\u30BF\u304C\u5B8C\u5168\u3067\u306A\u3044\u3053\u3068\u304C\u3042\u308A\u307E\u3059\u3002 -HashDbConfigPanel.noSelectionText=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304C\u9078\u629E\u3055\u308C\u3066\u3044\u307E\u305B\u3093 -HashDbConfigPanel.errorGettingPathText=\u30D1\u30B9\u306E\u53D6\u5F97\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F -HashDbConfigPanel.errorGettingIndexStatusText=\u30B9\u30C6\u30FC\u30BF\u30B9\u306E\u78BA\u8A8D\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F -HashDbConfigPanel.setName.hashSetConfig=\u30CF\u30C3\u30B7\u30E5\u30BB\u30C3\u30C8\u8A2D\u5B9A -HashDbConfigPanel.indexButtonText.index=\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9 -HashDbConfigPanel.indexButtonText.indexing=\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u4E2D -HashDbConfigPanel.indexStatusText.indexGen=\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u3092\u4F5C\u6210\u4E2D\u3067\u3059 -HashDbConfigPanel.indexStatusText.indexOnly=\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u306E\u307F -HashDbConfigPanel.indexStatusText.indexed=\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u6E08\u307F -HashDbConfigPanel.indexButtonText.reIndex=\u518D\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9 -HashDbConfigPanel.indexStatusText.noIndex=\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u7121\u3057 -HashDbConfigPanel.dbsNotIndexedMsg=\u6B21\u306E\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306F\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u3057\u307E\u3059\u304B\uFF1F\n {0} -HashDbConfigPanel.unindexedDbsMsg=\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u3055\u308C\u3066\u3044\u306A\u3044\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9 -HashDbConfigPanel.allUnindexedDbsRmFromListMsg=\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u3055\u308C\u3066\u3044\u306A\u3044\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306F\u30EA\u30B9\u30C8\u304B\u3089\u524A\u9664\u3055\u308C\u307E\u3059 -HashDbConfigPanel.nameColLbl=\u540D\u524D -HashDbConfigPanel.editingCellsNotSupportedMsg=\u30BB\u30EB\u306F\u7DE8\u96C6\u4E0D\u53EF\u3067\u3059 -HashDbConfigPanel.deleteDbActionConfirmMsg=\u5168\u3066\u306E\u30B1\u30FC\u30B9\u306B\u304A\u3051\u308B\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u524A\u9664\u3057\u307E\u3059\u3002\u5B9F\u884C\u3057\u307E\u3059\u304B\uFF1F -HashDbConfigPanel.deleteDbActionMsg=\u8A2D\u5B9A\u304B\u3089\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u524A\u9664 -HashDbCreateDatabaseDialog.createHashDbMsg=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u4F5C\u6210 -HashDbCreateDatabaseDialog.hashDbMustHaveFileExtensionMsg=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30D5\u30A1\u30A4\u30EB\u306F .{0} \u306E\u62E1\u5F35\u5B50\u304C\u5FC5\u8981\u3067\u3059\u3002 -HashDbCreateDatabaseDialog.fileNameErr=\u30D5\u30A1\u30A4\u30EB\u540D\u30A8\u30E9\u30FC -HashDbCreateDatabaseDialog.fileNameAlreadyExistsMsg=\u540C\u540D\u306E\u30D5\u30A1\u30A4\u30EB\u304C\u65E2\u306B\u5B58\u5728\u3057\u307E\u3059\u3002\u5225\u306E\u30D5\u30A1\u30A4\u30EB\u540D\u3092\u8A2D\u5B9A\u3057\u3066\u4E0B\u3055\u3044\u3002 -HashDbCreateDatabaseDialog.fileExistsErr=\u30D5\u30A1\u30A4\u30EB\u304C\u65E2\u306B\u5B58\u5728\u3057\u3066\u3044\u308B\u30A8\u30E9\u30FC -HashDbCreateDatabaseDialog.mustEnterHashSetNameMsg=\u30CF\u30C3\u30B7\u30E5\u30BB\u30C3\u30C8\u540D\u306E\u5165\u529B\u304C\u5FC5\u8981\u3067\u3059 -HashDbCreateDatabaseDialog.createHashDbErr=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u4F5C\u6210\u30A8\u30E9\u30FC -HashDbCreateDatabaseDialog.mustEnterHashDbPathMsg=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30D1\u30B9\u306E\u5165\u529B\u304C\u5FC5\u8981\u3067\u3059\u3002 -HashDbCreateDatabaseDialog.errMsg.hashDbCreationErr=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u4F5C\u6210\u30A8\u30E9\u30FC -HashDbCreateDatabaseDialog.cannotCreateFileAtLocMsg=\u6307\u5B9A\u3055\u308C\u305F\u30ED\u30B1\u30FC\u30B7\u30E7\u30F3\u3067\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30D5\u30A1\u30A4\u30EB\u3092\u4F5C\u6210\u3067\u304D\u307E\u305B\u3093\u3002 -HashDbCreateDatabaseDialog.failedToCreateHashDbMsg=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306E\u4F5C\u6210\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002 -HashDbImportDatabaseDialog.importHashDbMsg=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u30A4\u30F3\u30DD\u30FC\u30C8 -HashDbImportDatabaseDialog.fileNameExtFilter.text=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30D5\u30A1\u30A4\u30EB -HashDbImportDatabaseDialog.failedToGetDbPathMsg=\u9078\u629E\u3057\u305F\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306E\u30D1\u30B9\u306E\u5165\u624B\u3092\u5931\u6557\u3057\u307E\u3057\u305F\u3002 -HashDbImportDatabaseDialog.importHashDbErr=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306E\u30A8\u30E9\u30FC\u3092\u30A4\u30F3\u30DD\u30FC\u30C8 -HashDbImportDatabaseDialog.mustSelectHashDbFilePathMsg=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306E\u30D5\u30A1\u30A4\u30EB\u30D1\u30B9\u306E\u9078\u629E\u304C\u5FC5\u8981\u3067\u3059\u3002 -HashDbImportDatabaseDialog.hashDbDoesNotExistMsg=\u9078\u629E\u3055\u308C\u305F\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306F\u5B58\u5728\u3057\u307E\u305B\u3093\u3002 -HashDbImportDatabaseDialog.errorMessage.failedToOpenHashDbMsg={0}\u3067\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u958B\u304F\u306E\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002 -HashDbIngestModule.moduleName=\u30CF\u30C3\u30B7\u30E5\u30EB\u30C3\u30AF\u30A2\u30C3\u30D7 -HashDbIngestModule.moduleDescription=\u6A19\u6E96\u306ENSRL\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306A\u3069\u3001\u63D0\u4F9B\u3055\u308C\u305F\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u5229\u7528\u3057\u3066\u3001\u65E2\u77E5\u307E\u305F\u306F\u7591\u308F\u3057\u3044\u3082\u306E\u3092\u691C\u77E5\u3057\u307E\u3059\u3002 -HashDbIngestModule.noKnownHashDbSetMsg=\u65E2\u77E5\u306E\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304C\u5B58\u5728\u3057\u307E\u305B\u3093\u3002 -HashDbIngestModule.knownFileSearchWillNotExecuteWarn=\u65E2\u77E5\u306E\u30D5\u30A1\u30A4\u30EB\u691C\u7D22\u304C\u5B9F\u884C\u3055\u308C\u307E\u305B\u3093\u3002 -HashDbIngestModule.noKnownBadHashDbSetMsg=\u65E2\u77E5\u306E\u60AA\u8CEA\u306A\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30BB\u30C3\u30C8\u306F\u3042\u308A\u307E\u305B\u3093\u3002 -HashDbConfigPanel.dbNotIndexedMsg=\u6B21\u306E\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306F\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u3057\u307E\u3059\u304B\uFF1F\n{0} -HashDbIngestModule.knownBadFileSearchWillNotExecuteWarn=\u65E2\u77E5\u306E\u60AA\u8CEA\u30D5\u30A1\u30A4\u30EB\u691C\u7D22\u306F\u5B9F\u884C\u3055\u308C\u307E\u305B\u3093\u3002 -HashDbIngestModule.fileReadErrorMsg=\u8AAD\u307F\u8FBC\u307F\u30A8\u30E9\u30FC\uFF1A {0} -HashDbIngestModule.calcHashValueErr={0}\u306E\u30CF\u30C3\u30B7\u30E5\u5024\u3092\u8A08\u7B97\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002 -HashDbIngestModule.hashLookupErrorMsg=\u30CF\u30C3\u30B7\u30E5\u30EB\u30C3\u30AF\u30A2\u30C3\u30D7\u30A8\u30E9\u30FC\uFF1A {0} -HashDbIngestModule.settingKnownBadStateErr={0}\u306E\u65E2\u77E5\u306E\u60AA\u8CEA\u30B9\u30C6\u30FC\u30BF\u30B9\u3092\u8A2D\u5B9A\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002 -HashDbIngestModule.lookingUpKnownBadHashValueErr={0}\u306E\u65E2\u77E5\u306E\u60AA\u8CEA\u30CF\u30C3\u30B7\u30E5\u5024\u3092\u30EB\u30C3\u30AF\u30A2\u30C3\u30D7\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002 -HashDbIngestModule.lookingUpKnownHashValueErr={0}\u306E\u65E2\u77E5\u306E\u30CF\u30C3\u30B7\u30E5\u5024\u3092\u30EB\u30C3\u30AF\u30A2\u30C3\u30D7\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002 -HashDbIngestModule.postToBB.fileName=\u30D5\u30A1\u30A4\u30EB\u540D -HashDbIngestModule.postToBB.md5Hash=MD5\u30CF\u30C3\u30B7\u30E5 -HashDbIngestModule.postToBB.hashsetName=\u30CF\u30C3\u30B7\u30E5\u30BB\u30C3\u30C8\u540D -HashDbIngestModule.postToBB.knownBadMsg=\u65E2\u77E5\u306E\u60AA\u8CEA\: {0} -HashDbIngestModule.complete.knownBadsFound=\u767A\u898B\u3055\u308C\u305F\u65E2\u77E5\u306E\u60AA\u8CEA\uFF1A -HashDbIngestModule.complete.totalCalcTime=\u8A08\u7B97\u6642\u9593\u306E\u5408\u8A08 -HashDbIngestModule.complete.totalLookupTime=\u30EB\u30C3\u30AF\u30A2\u30C3\u30D7\u6642\u9593\u306E\u5408\u8A08 -HashDbIngestModule.complete.databasesUsed=\u5229\u7528\u3057\u305F\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\uFF1A -HashDbIngestModule.complete.hashLookupResults=\u30CF\u30C3\u30B7\u30E5\u30EB\u30C3\u30AF\u30A2\u30C3\u30D7\u7D50\u679C -HashDbManager.moduleErrorListeningToUpdatesMsg=HashDbManager\u30A2\u30C3\u30D7\u30C7\u30FC\u30C8\u3092\u78BA\u8A8D\u4E2D\u306B\u30E2\u30B8\u30E5\u30FC\u30EB\u304C\u30A8\u30E9\u30FC\u3092\u8D77\u3053\u3057\u307E\u3057\u305F\u3002\u3069\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u304C\u539F\u56E0\u306A\u306E\u304B\u3092\u30ED\u30B0\u3092\u78BA\u8A8D\u3057\u3066\u4E0B\u3055\u3044\u3002\u4E00\u90E8\u306E\u30C7\u30FC\u30BF\u304C\u5B8C\u5168\u3067\u306A\u3044\u3053\u3068\u304C\u3042\u308A\u307E\u3059\u3002 -HashDbManager.replacingDuplicateHashsetNameMsg=\u91CD\u8907\u306E\u30CF\u30C3\u30B7\u30E5\u30BB\u30C3\u30C8\u540D {0} \u304C\u898B\u3064\u304B\u308A\u307E\u3057\u305F\u3002\n {1}\u306B\u66F8\u304D\u63DB\u3048\u307E\u3059\u3002 -HashDbManager.openHashDbErr=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u958B\u304F\u30A8\u30E9\u30FC -HashDbManager.unableToOpenHashDbMsg=\ {0} \u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u958B\u3051\u307E\u305B\u3093\u3002 -HashDbManager.savedBackupOfOldConfigMsg={0}\n\u53E4\u3044\u8A2D\u5B9A\u306E\u30D0\u30C3\u30AF\u30A2\u30C3\u30D7\u30B3\u30D4\u30FC\u304C\u6B21\u306E\u901A\u308A\u4FDD\u5B58\u3055\u308C\u307E\u3057\u305F\u3002\n{1} -HashDbManager.baseMessage.updatedFormatHashDbConfig=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u8A2D\u5B9A\u30D5\u30A1\u30A4\u30EB\u306E\u5F62\u5F0F\u304C\u66F4\u65B0\u3055\u308C\u307E\u3057\u305F\u3002 -HashDbManager.msgBoxTitle.confFileFmtChanged=\u8A2D\u5B9A\u30D5\u30A1\u30A4\u30EB\u5F62\u5F0F\u306E\u5909\u66F4\u5B8C\u4E86 -HashDbManager.dlgMsg.dbNotFoundAtLoc=\ {0} \u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306F\u6B21\u306E\u30ED\u30B1\u30FC\u30B7\u30E7\u30F3\u306B\u3042\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002\n {1}\n \u30D5\u30A1\u30A4\u30EB\u3092\u691C\u7D22\u3057\u307E\u3059\u304B\uFF1F -HashDbManager.dlgTitle.MissingDb=\u6B20\u843D\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9 -HashDbManager.progress.indexingHashSet=\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u4E2D {0} -HashDbManager.dlgMsg.errorIndexingHashSet=\ {0} \u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306E\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u4E2D\u306E\u30A8\u30E9\u30FC -HashDbManager.hashDbIndexingErr=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306E\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u4E2D\u306E\u30A8\u30E9\u30FC -HashDbPanelSearchAction.actionName=MD5\u30CF\u30C3\u30B7\u30E5\u306B\u57FA\u3065\u304F\u30D5\u30A1\u30A4\u30EB\u691C\u7D22 -HashDbSearchAction.dlgMsg.noFilesHaveMD5Calculated=MD5\u30CF\u30C3\u30B7\u30E5\u304C\u8A08\u7B97\u3055\u308C\u3066\u3044\u308B\u30D5\u30A1\u30A4\u30EB\u304C\u3042\u308A\u307E\u305B\u3093\u3002\u307E\u305A\u306FHashDB\u3092\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u3057\u3066\u4E0B\u3055\u3044\u3002 -HashDbSearchManager.MD5HashSearch=MD5\u30CF\u30C3\u30B7\u30E5\u691C\u7D22 -HashDbSearchManager.noResultsFoundMsg=\u4E00\u81F4\u3059\u308B\u3082\u306E\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002 -HashDbSearchPanel.titleText.ingestOngoing=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u4E2D\uFF1B\u5B8C\u4E86\u3059\u308B\u307E\u3067\u3053\u306E\u30B5\u30FC\u30D3\u30B9\u306F\u5229\u7528\u3067\u304D\u307E\u305B\u3093\u3002 -HashDbSearchPanel.noFilesHaveMD5HashMsg=MD5\u30CF\u30C3\u30B7\u30E5\u4ED8\u304D\u306E\u30D5\u30A1\u30A4\u30EB\u304C\u3042\u308A\u307E\u305B\u3093\u3002 -HashDbSearchPanel.errorText.noHashesAddedMsg=\u30A8\u30E9\u30FC\uFF1A\u30CF\u30C3\u30B7\u30E5\u304C\u8FFD\u52A0\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002 -HashDbSearchPanel.errorText.hashAlreadyAddedMsg=\u30A8\u30E9\u30FC\uFF1A\u30CF\u30C3\u30B7\u30E5\u304C\u65E2\u306B\u8FFD\u52A0\u3055\u308C\u3066\u3044\u307E\u3059\u3002 -HashDbSearchPanel.errorText.invalidMD5HashMsg=\u30A8\u30E9\u30FC\uFF1A\u6709\u52B9\u306AMD5\u30CF\u30C3\u30B7\u30E5\u3067\u306F\u3042\u308A\u307E\u305B\u3093\u3002 -HashDbSearchThread.progress.cancellingSearch={0}\uFF08\u30AD\u30E3\u30F3\u30BB\u30EB\u4E2D\u2026\uFF09 -HashDbSearchThread.name.searching=\u691C\u7D22\u4E2D -HashDbSearchThread.noMoreFilesWithMD5Msg=\u540C\u3058MD5\u30CF\u30C3\u30B7\u30E5\u4ED8\u304D\u306E\u30D5\u30A1\u30A4\u30EB\u306F\u4ED6\u306B\u3042\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002 -ModalNoButtons.indexingDbsTitle=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u4E2D -ModalNoButtons.indexingDbTitle=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u4E2D -ModalNoButtons.exitHashDbIndexingMsg=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306E\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u3092\u4E2D\u6B62\u3057\u307E\u3059\u3002\n\ -\u4F5C\u6210\u3055\u308C\u305F\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u306F\u5229\u7528\u4E0D\u53EF\u3068\u306A\u308A\u307E\u3059\u3002\u7D9A\u884C\u3059\u308B\u5834\u5408\u306F\n\ -\u30CF\u30C3\u30B7\u30E5\u30D5\u30A9\u30EB\u30C0\u5185\u306B\u3042\u308B\u3001\u5BFE\u5FDC\u3059\u308B-md5.idx \u30D5\u30A1\u30A4\u30EB\u3092\u524A\u9664\u3057\u3066\u4E0B\u3055\u3044\u3002\n\ -\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u3092\u4E2D\u6B62\u3057\u307E\u3059\u304B\uFF1F -ModalNoButtons.dlgTitle.unfinishedIndexing=\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u672A\u5B8C\u4E86 -ModalNoButtons.indexThis.currentlyIndexing1Db=\uFF11\u3064\u306E\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u4E2D -ModalNoButtons.indexThese.currentlyIndexing1OfNDbs=\uFF11\uFF0F {0}\u3064\u76EE\u3092\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u4E2D -ModalNoButtons.propChg.currentlyIndexingXofN={0}\uFF0F {1}\u3064\u76EE\u3092\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u4E2D -HashDbManager.duplicateHashSetNameExceptionMsg=\u30CF\u30C3\u30B7\u30E5\u30BB\u30C3\u30C8\u540D''{0}''\u306F\u65E2\u306B\u5225\u306E\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306B\u4F7F\u308F\u308C\u3066\u3044\u307E\u3059\u3002 -HashDbManager.hashDbDoesNotExistExceptionMsg=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304C\u6B21\u3067\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F\n{0} -HashDbManager.hashDbFileExistsExceptionMsg=\u65E2\u306B\u30D5\u30A1\u30A4\u30EB\u304C\u6B21\u306B\u5B58\u5728\u3057\u307E\u3059\n{0} -HashDbManager.hashDbAlreadyAddedExceptionMsg=\u6B21\u306E\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\n{0}\n\u306F\u65E2\u306B\u4F5C\u6210\u307E\u305F\u306F\u30A4\u30F3\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u307E\u3059\u3002 -HashDbManager.illegalHashDbFileNameExtensionMsg=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30D5\u30A1\u30A4\u30EB\u540D\u306F.{0}\u306E\u62E1\u5F35\u5B50\u304C\u5FC5\u8981\u3067\u3059\u3002 -HashDbManager.moduleErr=\u30E2\u30B8\u30E5\u30FC\u30EB\u30A8\u30E9\u30FC -HashDbManager.knownBad.text=\u65E2\u77E5\u306E\u60AA\u8CEA -HashDbManager.known.text=\u65E2\u77E5 -HashDbManager.fileNameExtensionFilter.title=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30D5\u30A1\u30A4\u30EB -HashDbSearchAction.dlgMsg.title=MD5\u30CF\u30C3\u30B7\u30E5\u306B\u57FA\u3065\u3044\u305F\u30D5\u30A1\u30A4\u30EB\u691C\u7D22 -HashDbSearchAction.getName.text=\u30CF\u30C3\u30B7\u30E5\u691C\u7D22 -HashDbSearchPanel.dlgMsg.title=MD5\u30CF\u30C3\u30B7\u30E5\u306B\u57FA\u3065\u304F\u30D5\u30A1\u30A4\u30EB\u691C\u7D22 -AddContentToHashDbAction.singleSelectionName=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306B\u30D5\u30A1\u30A4\u30EB\u3092\u8FFD\u52A0 -AddContentToHashDbAction.multipleSelectionName=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306B\u30D5\u30A1\u30A4\u30EB\u3092\u8FFD\u52A0 -OptionsCategory_Name_HashDatabase=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9 -OptionsCategory_Keywords_HashDatabase=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9 -HashDbManager.ingestRunningExceptionMsg=\u51E6\u7406\u4E2D\uFF1B\u5B8C\u4E86\u3059\u308B\u307E\u3067\u3053\u306E\u30B5\u30FC\u30D3\u30B9\u306F\u5229\u7528\u3067\u304D\u307E\u305B\u3093\u3002 -ModalNoButtons.CURRENTDB_LABEL.text=\uFF08\u73FE\u5728\u306E\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\uFF09 -HashDbCreateDatabaseDialog.defaultFileName=\u30CF\u30C3\u30B7\u30E5\u30BB\u30C3\u30C8 -HashDbManager.saveErrorExceptionMsg=\u30CF\u30C3\u30B7\u30E5\u8A2D\u5B9A\u306E\u4FDD\u5B58\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F -AddContentToHashDbAction.addFilesToHashSet.files=\u30D5\u30A1\u30A4\u30EB -AddContentToHashDbAction.addFilesToHashSet.file=\u30D5\u30A1\u30A4\u30EB -HashDbManager.errCreatingIndex.title=\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u306E\u4F5C\u6210\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F -HashDbManager.errCreatingIndex.msg=\u6B21\u306E\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u306E\u4F5C\u6210\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\uFF1A {0} +AddContentToHashDbAction.ContentMenu.noHashDbsConfigd=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u305b\u3093 +AddContentToHashDbAction.ContentMenu.createDbItem=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u4f5c\u6210... +AddContentToHashDbAction.addFilesToHashSet.addToHashDbErr1.text=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30a8\u30e9\u30fc\u306b\u8ffd\u52a0 +AddContentToHashDbAction.addFilesToHashSet.addToHashDbErr2.text=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30a8\u30e9\u30fc\u306b\u8ffd\u52a0 +AddContentToHashDbAction.addFilesToHashSet.addToHashDbErr3.text=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30a8\u30e9\u30fc\u306b\u8ffd\u52a0 +AddContentToHashDbAction.addFilesToHashSet.unableToAddFileMsg=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306b{0}\u3092\u8ffd\u52a0\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +AddContentToHashDbAction.addFilesToHashSet.unableToAddFileSzMsg=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306b{0}\u3092\u8ffd\u52a0\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u30cf\u30c3\u30b7\u30e5\u304c\u8a08\u7b97\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002\u9069\u5207\u306a\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u8a2d\u5b9a\u3057\u3001\u5b9f\u884c\u3057\u3066\u4e0b\u3055\u3044\u3002 +HashDatabaseOptionsPanelController.moduleErr=\u30e2\u30b8\u30e5\u30fc\u30eb\u30a8\u30e9\u30fc +HashDatabaseOptionsPanelController.moduleErrMsg=HashDatabaseOptionsPanelController\u306e\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u3092\u78ba\u8a8d\u4e2d\u306b\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u30a8\u30e9\u30fc\u3092\u8d77\u3053\u3057\u307e\u3057\u305f\u3002\u3069\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u304b\u30ed\u30b0\u3092\u78ba\u8a8d\u3057\u3066\u4e0b\u3055\u3044\u3002\u4e00\u90e8\u306e\u30c7\u30fc\u30bf\u304c\u5b8c\u5168\u3067\u306a\u3044\u3053\u3068\u304c\u3042\u308a\u307e\u3059\u3002 +HashDbConfigPanel.noSelectionText=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u307e\u305b\u3093 +HashDbConfigPanel.errorGettingPathText=\u30d1\u30b9\u306e\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +HashDbConfigPanel.errorGettingIndexStatusText=\u30b9\u30c6\u30fc\u30bf\u30b9\u306e\u78ba\u8a8d\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +HashDbConfigPanel.indexButtonText.index=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9 +HashDbConfigPanel.indexButtonText.indexing=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u4e2d +HashDbConfigPanel.indexStatusText.indexGen=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u3092\u4f5c\u6210\u4e2d\u3067\u3059 +HashDbConfigPanel.indexStatusText.indexOnly=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306e\u307f +HashDbConfigPanel.indexStatusText.indexed=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u6e08\u307f +HashDbConfigPanel.indexButtonText.reIndex=\u518d\u30a4\u30f3\u30c7\u30c3\u30af\u30b9 +HashDbConfigPanel.indexStatusText.noIndex=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u7121\u3057 +HashDbConfigPanel.dbsNotIndexedMsg=\u6b21\u306e\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306f\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u3057\u307e\u3059\u304b\uff1f\n {0} +HashDbConfigPanel.unindexedDbsMsg=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u3055\u308c\u3066\u3044\u306a\u3044\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9 +HashDbConfigPanel.allUnindexedDbsRmFromListMsg=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u3055\u308c\u3066\u3044\u306a\u3044\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306f\u30ea\u30b9\u30c8\u304b\u3089\u524a\u9664\u3055\u308c\u307e\u3059 +HashDbConfigPanel.nameColLbl=\u540d\u524d +HashDbConfigPanel.editingCellsNotSupportedMsg=\u30bb\u30eb\u306f\u7de8\u96c6\u4e0d\u53ef\u3067\u3059 +HashDbConfigPanel.deleteDbActionConfirmMsg=\u5168\u3066\u306e\u30b1\u30fc\u30b9\u306b\u304a\u3051\u308b\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u524a\u9664\u3057\u307e\u3059\u3002\u5b9f\u884c\u3057\u307e\u3059\u304b\uff1f +HashDbConfigPanel.deleteDbActionMsg=\u8a2d\u5b9a\u304b\u3089\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u524a\u9664 +HashDbCreateDatabaseDialog.createHashDbMsg=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u4f5c\u6210 +HashDbCreateDatabaseDialog.hashDbMustHaveFileExtensionMsg=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb\u306f .{0} \u306e\u62e1\u5f35\u5b50\u304c\u5fc5\u8981\u3067\u3059\u3002 +HashDbCreateDatabaseDialog.fileNameErr=\u30d5\u30a1\u30a4\u30eb\u540d\u30a8\u30e9\u30fc +HashDbCreateDatabaseDialog.fileNameAlreadyExistsMsg=\u540c\u540d\u306e\u30d5\u30a1\u30a4\u30eb\u304c\u65e2\u306b\u5b58\u5728\u3057\u307e\u3059\u3002\u5225\u306e\u30d5\u30a1\u30a4\u30eb\u540d\u3092\u8a2d\u5b9a\u3057\u3066\u4e0b\u3055\u3044\u3002 +HashDbCreateDatabaseDialog.fileExistsErr=\u30d5\u30a1\u30a4\u30eb\u304c\u65e2\u306b\u5b58\u5728\u3057\u3066\u3044\u308b\u30a8\u30e9\u30fc +HashDbCreateDatabaseDialog.mustEnterHashSetNameMsg=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u540d\u306e\u5165\u529b\u304c\u5fc5\u8981\u3067\u3059 +HashDbCreateDatabaseDialog.createHashDbErr=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u4f5c\u6210\u30a8\u30e9\u30fc +HashDbCreateDatabaseDialog.mustEnterHashDbPathMsg=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30d1\u30b9\u306e\u5165\u529b\u304c\u5fc5\u8981\u3067\u3059\u3002 +HashDbCreateDatabaseDialog.errMsg.hashDbCreationErr=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u4f5c\u6210\u30a8\u30e9\u30fc +HashDbCreateDatabaseDialog.cannotCreateFileAtLocMsg=\u6307\u5b9a\u3055\u308c\u305f\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3\u3067\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3002 +HashDbCreateDatabaseDialog.failedToCreateHashDbMsg=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u4f5c\u6210\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 +HashDbImportDatabaseDialog.importHashDbMsg=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u30a4\u30f3\u30dd\u30fc\u30c8 +HashDbImportDatabaseDialog.fileNameExtFilter.text=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb +HashDbImportDatabaseDialog.failedToGetDbPathMsg=\u9078\u629e\u3057\u305f\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30d1\u30b9\u306e\u5165\u624b\u3092\u5931\u6557\u3057\u307e\u3057\u305f\u3002 +HashDbImportDatabaseDialog.importHashDbErr=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30a8\u30e9\u30fc\u3092\u30a4\u30f3\u30dd\u30fc\u30c8 +HashDbImportDatabaseDialog.mustSelectHashDbFilePathMsg=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30d5\u30a1\u30a4\u30eb\u30d1\u30b9\u306e\u9078\u629e\u304c\u5fc5\u8981\u3067\u3059\u3002 +HashDbImportDatabaseDialog.hashDbDoesNotExistMsg=\u9078\u629e\u3055\u308c\u305f\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306f\u5b58\u5728\u3057\u307e\u305b\u3093\u3002 +HashDbImportDatabaseDialog.errorMessage.failedToOpenHashDbMsg={0}\u3067\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u958b\u304f\u306e\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 +HashDbIngestModule.moduleName=\u30cf\u30c3\u30b7\u30e5\u30eb\u30c3\u30af\u30a2\u30c3\u30d7 +HashDbIngestModule.moduleDescription=\u6a19\u6e96\u306eNSRL\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306a\u3069\u3001\u63d0\u4f9b\u3055\u308c\u305f\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u5229\u7528\u3057\u3066\u3001\u65e2\u77e5\u307e\u305f\u306f\u7591\u308f\u3057\u3044\u3082\u306e\u3092\u691c\u77e5\u3057\u307e\u3059\u3002 +HashDbIngestModule.noKnownHashDbSetMsg=\u65e2\u77e5\u306e\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u5b58\u5728\u3057\u307e\u305b\u3093\u3002 +HashDbIngestModule.knownFileSearchWillNotExecuteWarn=\u65e2\u77e5\u306e\u30d5\u30a1\u30a4\u30eb\u691c\u7d22\u304c\u5b9f\u884c\u3055\u308c\u307e\u305b\u3093\u3002 +HashDbIngestModule.noKnownBadHashDbSetMsg=\u65e2\u77e5\u306e\u60aa\u8cea\u306a\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30bb\u30c3\u30c8\u306f\u3042\u308a\u307e\u305b\u3093\u3002 +HashDbConfigPanel.dbNotIndexedMsg=\u6b21\u306e\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306f\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u3057\u307e\u3059\u304b\uff1f\n{0} +HashDbIngestModule.knownBadFileSearchWillNotExecuteWarn=\u65e2\u77e5\u306e\u60aa\u8cea\u30d5\u30a1\u30a4\u30eb\u691c\u7d22\u306f\u5b9f\u884c\u3055\u308c\u307e\u305b\u3093\u3002 +HashDbIngestModule.fileReadErrorMsg=\u8aad\u307f\u8fbc\u307f\u30a8\u30e9\u30fc\uff1a {0} +HashDbIngestModule.calcHashValueErr={0}\u306e\u30cf\u30c3\u30b7\u30e5\u5024\u3092\u8a08\u7b97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +HashDbIngestModule.hashLookupErrorMsg=\u30cf\u30c3\u30b7\u30e5\u30eb\u30c3\u30af\u30a2\u30c3\u30d7\u30a8\u30e9\u30fc\uff1a {0} +HashDbIngestModule.settingKnownBadStateErr={0}\u306e\u65e2\u77e5\u306e\u60aa\u8cea\u30b9\u30c6\u30fc\u30bf\u30b9\u3092\u8a2d\u5b9a\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +HashDbIngestModule.lookingUpKnownBadHashValueErr={0}\u306e\u65e2\u77e5\u306e\u60aa\u8cea\u30cf\u30c3\u30b7\u30e5\u5024\u3092\u30eb\u30c3\u30af\u30a2\u30c3\u30d7\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +HashDbIngestModule.lookingUpKnownHashValueErr={0}\u306e\u65e2\u77e5\u306e\u30cf\u30c3\u30b7\u30e5\u5024\u3092\u30eb\u30c3\u30af\u30a2\u30c3\u30d7\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +HashDbIngestModule.postToBB.fileName=\u30d5\u30a1\u30a4\u30eb\u540d +HashDbIngestModule.postToBB.md5Hash=MD5\u30cf\u30c3\u30b7\u30e5 +HashDbIngestModule.postToBB.hashsetName=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u540d +HashDbIngestModule.postToBB.knownBadMsg=\u65e2\u77e5\u306e\u60aa\u8cea\: {0} +HashDbIngestModule.complete.knownBadsFound=\u767a\u898b\u3055\u308c\u305f\u65e2\u77e5\u306e\u60aa\u8cea\uff1a +HashDbIngestModule.complete.totalCalcTime=\u8a08\u7b97\u6642\u9593\u306e\u5408\u8a08 +HashDbIngestModule.complete.totalLookupTime=\u30eb\u30c3\u30af\u30a2\u30c3\u30d7\u6642\u9593\u306e\u5408\u8a08 +HashDbIngestModule.complete.databasesUsed=\u5229\u7528\u3057\u305f\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\uff1a +HashDbIngestModule.complete.hashLookupResults=\u30cf\u30c3\u30b7\u30e5\u30eb\u30c3\u30af\u30a2\u30c3\u30d7\u7d50\u679c +HashDbManager.moduleErrorListeningToUpdatesMsg=HashDbManager\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u3092\u78ba\u8a8d\u4e2d\u306b\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u30a8\u30e9\u30fc\u3092\u8d77\u3053\u3057\u307e\u3057\u305f\u3002\u3069\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u539f\u56e0\u306a\u306e\u304b\u3092\u30ed\u30b0\u3092\u78ba\u8a8d\u3057\u3066\u4e0b\u3055\u3044\u3002\u4e00\u90e8\u306e\u30c7\u30fc\u30bf\u304c\u5b8c\u5168\u3067\u306a\u3044\u3053\u3068\u304c\u3042\u308a\u307e\u3059\u3002 +HashDbManager.replacingDuplicateHashsetNameMsg=\u91cd\u8907\u306e\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u540d {0} \u304c\u898b\u3064\u304b\u308a\u307e\u3057\u305f\u3002\n {1}\u306b\u66f8\u304d\u63db\u3048\u307e\u3059\u3002 +HashDbManager.openHashDbErr=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u958b\u304f\u30a8\u30e9\u30fc +HashDbManager.unableToOpenHashDbMsg=\ {0} \u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u958b\u3051\u307e\u305b\u3093\u3002 +HashDbManager.savedBackupOfOldConfigMsg={0}\n\u53e4\u3044\u8a2d\u5b9a\u306e\u30d0\u30c3\u30af\u30a2\u30c3\u30d7\u30b3\u30d4\u30fc\u304c\u6b21\u306e\u901a\u308a\u4fdd\u5b58\u3055\u308c\u307e\u3057\u305f\u3002\n{1} +HashDbManager.baseMessage.updatedFormatHashDbConfig=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\u306e\u5f62\u5f0f\u304c\u66f4\u65b0\u3055\u308c\u307e\u3057\u305f\u3002 +HashDbManager.msgBoxTitle.confFileFmtChanged=\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\u5f62\u5f0f\u306e\u5909\u66f4\u5b8c\u4e86 +HashDbManager.dlgMsg.dbNotFoundAtLoc=\ {0} \u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306f\u6b21\u306e\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3\u306b\u3042\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002\n {1}\n \u30d5\u30a1\u30a4\u30eb\u3092\u691c\u7d22\u3057\u307e\u3059\u304b\uff1f +HashDbManager.dlgTitle.MissingDb=\u6b20\u843d\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9 +HashDbManager.progress.indexingHashSet=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u4e2d {0} +HashDbManager.dlgMsg.errorIndexingHashSet=\ {0} \u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u4e2d\u306e\u30a8\u30e9\u30fc +HashDbManager.hashDbIndexingErr=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u4e2d\u306e\u30a8\u30e9\u30fc +HashDbPanelSearchAction.actionName=MD5\u30cf\u30c3\u30b7\u30e5\u306b\u57fa\u3065\u304f\u30d5\u30a1\u30a4\u30eb\u691c\u7d22 +HashDbSearchAction.dlgMsg.noFilesHaveMD5Calculated=MD5\u30cf\u30c3\u30b7\u30e5\u304c\u8a08\u7b97\u3055\u308c\u3066\u3044\u308b\u30d5\u30a1\u30a4\u30eb\u304c\u3042\u308a\u307e\u305b\u3093\u3002\u307e\u305a\u306fHashDB\u3092\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3057\u3066\u4e0b\u3055\u3044\u3002 +HashDbSearchManager.MD5HashSearch=MD5\u30cf\u30c3\u30b7\u30e5\u691c\u7d22 +HashDbSearchManager.noResultsFoundMsg=\u4e00\u81f4\u3059\u308b\u3082\u306e\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +HashDbSearchPanel.titleText.ingestOngoing=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u4e2d\uff1b\u5b8c\u4e86\u3059\u308b\u307e\u3067\u3053\u306e\u30b5\u30fc\u30d3\u30b9\u306f\u5229\u7528\u3067\u304d\u307e\u305b\u3093\u3002 +HashDbSearchPanel.noFilesHaveMD5HashMsg=MD5\u30cf\u30c3\u30b7\u30e5\u4ed8\u304d\u306e\u30d5\u30a1\u30a4\u30eb\u304c\u3042\u308a\u307e\u305b\u3093\u3002 +HashDbSearchPanel.errorText.noHashesAddedMsg=\u30a8\u30e9\u30fc\uff1a\u30cf\u30c3\u30b7\u30e5\u304c\u8ffd\u52a0\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002 +HashDbSearchPanel.errorText.hashAlreadyAddedMsg=\u30a8\u30e9\u30fc\uff1a\u30cf\u30c3\u30b7\u30e5\u304c\u65e2\u306b\u8ffd\u52a0\u3055\u308c\u3066\u3044\u307e\u3059\u3002 +HashDbSearchPanel.errorText.invalidMD5HashMsg=\u30a8\u30e9\u30fc\uff1a\u6709\u52b9\u306aMD5\u30cf\u30c3\u30b7\u30e5\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002 +HashDbSearchThread.progress.cancellingSearch={0}\uff08\u30ad\u30e3\u30f3\u30bb\u30eb\u4e2d\u2026\uff09 +HashDbSearchThread.name.searching=\u691c\u7d22\u4e2d +HashDbSearchThread.noMoreFilesWithMD5Msg=\u540c\u3058MD5\u30cf\u30c3\u30b7\u30e5\u4ed8\u304d\u306e\u30d5\u30a1\u30a4\u30eb\u306f\u4ed6\u306b\u3042\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +ModalNoButtons.indexingDbsTitle=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u4e2d +ModalNoButtons.indexingDbTitle=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u4e2d +ModalNoButtons.exitHashDbIndexingMsg=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u3092\u4e2d\u6b62\u3057\u307e\u3059\u3002\n\ +\u4f5c\u6210\u3055\u308c\u305f\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306f\u5229\u7528\u4e0d\u53ef\u3068\u306a\u308a\u307e\u3059\u3002\u7d9a\u884c\u3059\u308b\u5834\u5408\u306f\n\ +\u30cf\u30c3\u30b7\u30e5\u30d5\u30a9\u30eb\u30c0\u5185\u306b\u3042\u308b\u3001\u5bfe\u5fdc\u3059\u308b-md5.idx \u30d5\u30a1\u30a4\u30eb\u3092\u524a\u9664\u3057\u3066\u4e0b\u3055\u3044\u3002\n\ +\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u3092\u4e2d\u6b62\u3057\u307e\u3059\u304b\uff1f +ModalNoButtons.dlgTitle.unfinishedIndexing=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u672a\u5b8c\u4e86 +ModalNoButtons.indexThis.currentlyIndexing1Db=\uff11\u3064\u306e\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u4e2d +ModalNoButtons.indexThese.currentlyIndexing1OfNDbs=\uff11\uff0f {0}\u3064\u76ee\u3092\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u4e2d +ModalNoButtons.propChg.currentlyIndexingXofN={0}\uff0f {1}\u3064\u76ee\u3092\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u4e2d +HashDbManager.duplicateHashSetNameExceptionMsg=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u540d''{0}''\u306f\u65e2\u306b\u5225\u306e\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306b\u4f7f\u308f\u308c\u3066\u3044\u307e\u3059\u3002 +HashDbManager.hashDbDoesNotExistExceptionMsg=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u6b21\u3067\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\n{0} +HashDbManager.hashDbFileExistsExceptionMsg=\u65e2\u306b\u30d5\u30a1\u30a4\u30eb\u304c\u6b21\u306b\u5b58\u5728\u3057\u307e\u3059\n{0} +HashDbManager.hashDbAlreadyAddedExceptionMsg=\u6b21\u306e\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\n{0}\n\u306f\u65e2\u306b\u4f5c\u6210\u307e\u305f\u306f\u30a4\u30f3\u30dd\u30fc\u30c8\u3055\u308c\u3066\u3044\u307e\u3059\u3002 +HashDbManager.illegalHashDbFileNameExtensionMsg=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb\u540d\u306f.{0}\u306e\u62e1\u5f35\u5b50\u304c\u5fc5\u8981\u3067\u3059\u3002 +HashDbManager.moduleErr=\u30e2\u30b8\u30e5\u30fc\u30eb\u30a8\u30e9\u30fc +HashDbManager.knownBad.text=\u65e2\u77e5\u306e\u60aa\u8cea +HashDbManager.known.text=\u65e2\u77e5 +HashDbManager.fileNameExtensionFilter.title=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb +HashDbSearchAction.dlgMsg.title=MD5\u30cf\u30c3\u30b7\u30e5\u306b\u57fa\u3065\u3044\u305f\u30d5\u30a1\u30a4\u30eb\u691c\u7d22 +HashDbSearchAction.getName.text=\u30cf\u30c3\u30b7\u30e5\u691c\u7d22 +HashDbSearchPanel.dlgMsg.title=MD5\u30cf\u30c3\u30b7\u30e5\u306b\u57fa\u3065\u304f\u30d5\u30a1\u30a4\u30eb\u691c\u7d22 +AddContentToHashDbAction.singleSelectionName=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306b\u30d5\u30a1\u30a4\u30eb\u3092\u8ffd\u52a0 +AddContentToHashDbAction.multipleSelectionName=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306b\u30d5\u30a1\u30a4\u30eb\u3092\u8ffd\u52a0 +OptionsCategory_Name_HashDatabase=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9 +OptionsCategory_Keywords_HashDatabase=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9 +HashDbManager.ingestRunningExceptionMsg=\u51e6\u7406\u4e2d\uff1b\u5b8c\u4e86\u3059\u308b\u307e\u3067\u3053\u306e\u30b5\u30fc\u30d3\u30b9\u306f\u5229\u7528\u3067\u304d\u307e\u305b\u3093\u3002 +ModalNoButtons.CURRENTDB_LABEL.text=\uff08\u73fe\u5728\u306e\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\uff09 +HashDbCreateDatabaseDialog.defaultFileName=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8 +HashDbManager.saveErrorExceptionMsg=\u30cf\u30c3\u30b7\u30e5\u8a2d\u5b9a\u306e\u4fdd\u5b58\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +AddContentToHashDbAction.addFilesToHashSet.files=\u30d5\u30a1\u30a4\u30eb +AddContentToHashDbAction.addFilesToHashSet.file=\u30d5\u30a1\u30a4\u30eb +HashDbManager.errCreatingIndex.title=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306e\u4f5c\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +HashDbManager.errCreatingIndex.msg=\u6b21\u306e\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306e\u4f5c\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a {0} -HashLookupSettingsPanel.optionsLabel.text=\u30AA\u30D7\u30B7\u30E7\u30F3 -HashLookupSettingsPanel.jButton3.text=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u30A4\u30F3\u30DD\u30FC\u30C8 -HashLookupSettingsPanel.indexPathLabelLabel.text=\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u30D1\u30B9\uFF1A -HashLookupSettingsPanel.createDatabaseButton.text=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u4F5C\u6210 -HashLookupSettingsPanel.jLabel6.text=\u30BF\u30A4\u30D7\uFF1A -HashLookupSettingsPanel.jLabel4.text=\u30ED\u30B1\u30FC\u30B7\u30E7\u30F3\uFF1A -HashLookupSettingsPanel.jLabel2.text=\u540D\u524D\uFF1A -HashLookupSettingsPanel.indexPathLabel.text=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304C\u9078\u629E\u3055\u308C\u3066\u3044\u307E\u305B\u3093 -HashLookupSettingsPanel.ingestWarningLabel.text=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u4E2D\u3067\u3059\u3002\u5B8C\u4E86\u3059\u308B\u307E\u3067\u4E00\u90E8\u306E\u8A2D\u5B9A\u306F\u5229\u7528\u3067\u304D\u307E\u305B\u3093\u3002 -HashLookupSettingsPanel.deleteDatabaseButton.text=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u524A\u9664 -HashLookupSettingsPanel.importDatabaseButton.text=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u30A4\u30F3\u30DD\u30FC\u30C8 -HashLookupSettingsPanel.hashDatabasesLabel.text=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\uFF1A -HashLookupSettingsPanel.nameLabel.text=\u30CF\u30C3\u30B7\u30E5\u30BB\u30C3\u30C8\u540D\uFF1A -HashLookupSettingsPanel.informationLabel.text=\u60C5\u5831 -HashLookupSettingsPanel.sendIngestMessagesCheckBox.text=\u30D2\u30C3\u30C8\u6BCE\u306B\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30A4\u30F3\u30DC\u30C3\u30AF\u30B9\u306B\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u9001\u308B -HashLookupSettingsPanel.hashDbLocationLabel.text=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304C\u9078\u629E\u3055\u308C\u3066\u3044\u307E\u305B\u3093 -HashLookupSettingsPanel.hashDbNameLabel.text=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304C\u9078\u629E\u3055\u308C\u3066\u3044\u307E\u305B\u3093 -HashLookupSettingsPanel.typeLabel.text=\u30BF\u30A4\u30D7\uFF1A -HashLookupSettingsPanel.locationLabel.text=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30D1\u30B9\uFF1A -HashLookupSettingsPanel.hashDbIndexStatusLabel.text=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304C\u9078\u629E\u3055\u308C\u3066\u3044\u307E\u305B\u3093 -HashLookupSettingsPanel.hashDbTypeLabel.text=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304C\u9078\u629E\u3055\u308C\u3066\u3044\u307E\u305B\u3093 -HashLookupSettingsPanel.indexButton.text=\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9 -HashLookupSettingsPanel.indexLabel.text=\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u30B9\u30C6\u30FC\u30BF\u30B9\uFF1A -HashLookupModuleSettingsPanel.alwaysCalcHashesCheckbox.text=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304C\u9078\u629E\u3055\u308C\u3066\u3044\u306A\u304F\u3066\u3082\u3001MD5\u3092\u8A08\u7B97 -HashLookupModuleSettingsPanel.knownHashDbsLabel.text=\u5229\u7528\u3059\u308B\u65E2\u77E5\u306E\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u9078\u629E\uFF1A -HashLookupModuleSettingsPanel.knownBadHashDbsLabel.text=\u51E6\u7406\u306B\u5229\u7528\u3059\u308B\u65E2\u77E5\u306E\u60AA\u8CEA\u306A\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u9078\u629E\uFF1A -HashLookupModuleFactory.createFileIngestModule.exception.msg=\u8A2D\u5B9A\u3092\u884C\u3046\u70BA\u306E\u60F3\u5B9A\u3055\u308C\u308B\u5F15\u6570\u306Finstanceof HashLookupModuleSettings\u3067\u3059\u3002 -HashLookupModuleFactory.getIngestJobSettingsPanel.exception.msg=\u8A2D\u5B9A\u3092\u884C\u3046\u70BA\u306E\u60F3\u5B9A\u3055\u308C\u308B\u5F15\u6570\u306Finstanceof HashLookupModuleSettings\u3067\u3059\u3002 -HashLookupModuleSettingsPanel.alwaysCalcHashesCheckbox.toolTipText=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304C\u9078\u629E\u3055\u308C\u3066\u3044\u306A\u304F\u3066\u3082\u3001MD5\u3092\u8A08\u7B97 -HashDbSearchPanel.hashTable.defaultModel.title.text=MD5\u30CF\u30C3\u30B7\u30E5 -AddContentToHashDbAction.addFilesToHashSet.unableToAddFileEmptyMsg=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306B{0}\u3092\u8FFD\u52A0\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u30D5\u30A1\u30A4\u30EB\u306B\u30B3\u30F3\u30C6\u30F3\u30C4\u304C\u3042\u308A\u307E\u305B\u3093\u3002 -AddHashValuesToDatabaseDialog.JDialog.Title=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306B\u30CF\u30C3\u30B7\u30E5\u3092\u8FFD\u52A0\ -HashLookupSettingsPanel.addHashesToDatabaseButton.text=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306B\u30CF\u30C3\u30B7\u30E5\u3092\u8FFD\u52A0 -AddHashValuesToDatabaseDialog.instructionLabel.text_1=\u4E0B\u8A18\u306BMD5\u306E\u30CF\u30C3\u30B7\u30E5\u5024\u3092\u8CBC\u308A\u4ED8\u3051\u308B\uFF08\u30E9\u30A4\u30F3\u3054\u3068\u306B\u4E00\u3064\u305A\u3064\uFF09\uFF1A -AddHashValuesToDatabaseDialog.cancelButton.text_2=\u30AD\u30E3\u30F3\u30BB\u30EB -AddHashValuesToDatabaseDialog.AddValuesToHashDatabaseButton.text_2=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306B\u30CF\u30C3\u30B7\u30E5\u3092\u8FFD\u52A0 -AddHashValuesToDatabaseDialog.pasteFromClipboardButton.text_2=\u30AF\u30EA\u30C3\u30D7\u30DC\u30FC\u30C9\u304B\u3089\u8CBC\u308A\u4ED8\u3051\u308B +HashLookupSettingsPanel.optionsLabel.text=\u30aa\u30d7\u30b7\u30e7\u30f3 +HashLookupSettingsPanel.jButton3.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u30a4\u30f3\u30dd\u30fc\u30c8 +HashLookupSettingsPanel.indexPathLabelLabel.text=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u30d1\u30b9\uff1a +HashLookupSettingsPanel.createDatabaseButton.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u4f5c\u6210 +HashLookupSettingsPanel.jLabel6.text=\u30bf\u30a4\u30d7\uff1a +HashLookupSettingsPanel.jLabel4.text=\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3\uff1a +HashLookupSettingsPanel.jLabel2.text=\u540d\u524d\uff1a +HashLookupSettingsPanel.indexPathLabel.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u307e\u305b\u3093 +HashLookupSettingsPanel.ingestWarningLabel.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u4e2d\u3067\u3059\u3002\u5b8c\u4e86\u3059\u308b\u307e\u3067\u4e00\u90e8\u306e\u8a2d\u5b9a\u306f\u5229\u7528\u3067\u304d\u307e\u305b\u3093\u3002 +HashLookupSettingsPanel.deleteDatabaseButton.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u524a\u9664 +HashLookupSettingsPanel.importDatabaseButton.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u30a4\u30f3\u30dd\u30fc\u30c8 +HashLookupSettingsPanel.hashDatabasesLabel.text=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\uff1a +HashLookupSettingsPanel.nameLabel.text=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u540d\uff1a +HashLookupSettingsPanel.informationLabel.text=\u60c5\u5831 +HashLookupSettingsPanel.sendIngestMessagesCheckBox.text=\u30d2\u30c3\u30c8\u6bce\u306b\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30a4\u30f3\u30dc\u30c3\u30af\u30b9\u306b\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u9001\u308b +HashLookupSettingsPanel.hashDbLocationLabel.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u307e\u305b\u3093 +HashLookupSettingsPanel.hashDbNameLabel.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u307e\u305b\u3093 +HashLookupSettingsPanel.typeLabel.text=\u30bf\u30a4\u30d7\uff1a +HashLookupSettingsPanel.locationLabel.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30d1\u30b9\uff1a +HashLookupSettingsPanel.hashDbIndexStatusLabel.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u307e\u305b\u3093 +HashLookupSettingsPanel.hashDbTypeLabel.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u307e\u305b\u3093 +HashLookupSettingsPanel.indexButton.text=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9 +HashLookupSettingsPanel.indexLabel.text=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u30b9\u30c6\u30fc\u30bf\u30b9\uff1a +HashLookupModuleSettingsPanel.alwaysCalcHashesCheckbox.text=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u306a\u304f\u3066\u3082\u3001MD5\u3092\u8a08\u7b97 +HashLookupModuleSettingsPanel.knownHashDbsLabel.text=\u5229\u7528\u3059\u308b\u65e2\u77e5\u306e\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u9078\u629e\uff1a +HashLookupModuleSettingsPanel.knownBadHashDbsLabel.text=\u51e6\u7406\u306b\u5229\u7528\u3059\u308b\u65e2\u77e5\u306e\u60aa\u8cea\u306a\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u9078\u629e\uff1a +HashLookupModuleFactory.createFileIngestModule.exception.msg=\u8a2d\u5b9a\u3092\u884c\u3046\u70ba\u306e\u60f3\u5b9a\u3055\u308c\u308b\u5f15\u6570\u306finstanceof HashLookupModuleSettings\u3067\u3059\u3002 +HashLookupModuleFactory.getIngestJobSettingsPanel.exception.msg=\u8a2d\u5b9a\u3092\u884c\u3046\u70ba\u306e\u60f3\u5b9a\u3055\u308c\u308b\u5f15\u6570\u306finstanceof HashLookupModuleSettings\u3067\u3059\u3002 +HashLookupModuleSettingsPanel.alwaysCalcHashesCheckbox.toolTipText=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u306a\u304f\u3066\u3082\u3001MD5\u3092\u8a08\u7b97 +HashDbSearchPanel.hashTable.defaultModel.title.text=MD5\u30cf\u30c3\u30b7\u30e5 +AddContentToHashDbAction.addFilesToHashSet.unableToAddFileEmptyMsg=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306b{0}\u3092\u8ffd\u52a0\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u30d5\u30a1\u30a4\u30eb\u306b\u30b3\u30f3\u30c6\u30f3\u30c4\u304c\u3042\u308a\u307e\u305b\u3093\u3002 +AddHashValuesToDatabaseDialog.JDialog.Title=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306b\u30cf\u30c3\u30b7\u30e5\u3092\u8ffd\u52a0\ +HashLookupSettingsPanel.addHashesToDatabaseButton.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306b\u30cf\u30c3\u30b7\u30e5\u3092\u8ffd\u52a0 +AddHashValuesToDatabaseDialog.instructionLabel.text_1=\u4e0b\u8a18\u306bMD5\u306e\u30cf\u30c3\u30b7\u30e5\u5024\u3092\u8cbc\u308a\u4ed8\u3051\u308b\uff08\u30e9\u30a4\u30f3\u3054\u3068\u306b\u4e00\u3064\u305a\u3064\uff09\uff1a +AddHashValuesToDatabaseDialog.cancelButton.text_2=\u30ad\u30e3\u30f3\u30bb\u30eb +AddHashValuesToDatabaseDialog.AddValuesToHashDatabaseButton.text_2=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306b\u30cf\u30c3\u30b7\u30e5\u3092\u8ffd\u52a0 +AddHashValuesToDatabaseDialog.pasteFromClipboardButton.text_2=\u30af\u30ea\u30c3\u30d7\u30dc\u30fc\u30c9\u304b\u3089\u8cbc\u308a\u4ed8\u3051\u308b AddHashValuesToDatabaseProgressDialog.okButton.text=OK -AddHashValuesToDatabaseProgressDialog.statusLabel.text=\u30B9\u30C6\u30FC\u30BF\u30B9 -AddHashValuesToDatabaseProgressDialog.title=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30D7\u30ED\u30B0\u30EC\u30B9\u306B\u30CF\u30C3\u30B7\u30E5\u3092\u8FFD\u52A0 -AddHashValuesToDatabaseDialog.title=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306B\u30CF\u30C3\u30B7\u30E5\u3092\u8FFD\u52A0 -AddHashValuesToDatabaseProgressDialog.showErrorsButton.text=\u30A8\u30E9\u30FC\u3092\u8868\u793A -AddHashValuesToDatabaseProgressDialog.addHashValuesToDatabase.parsing=MD5\u30CF\u30C3\u30B7\u30E5\u306B\u30C6\u30AD\u30B9\u30C8\u3092\u30D1\u30FC\u30B9\u4E2D... -AddHashValuesToDatabaseProgressDialog.addHashValuesToDatabase.invalidHash=\u30A4\u30F3\u30D7\u30C3\u30C8\u306B\u7121\u52B9\u306A\u30CF\u30C3\u30B7\u30E5\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\u3002 -AddHashValuesToDatabaseProgressDialog.addHashValuesToDatabase.invaliHash.msg=\u7121\u52B9\u306A\u30CF\u30C3\u30B7\u30E5\uFF1A -AddHashValuesToDatabaseProgressDialog.addHashValuesToDatabase.noHashesToAdd=\u8FFD\u52A0\u3059\u308B\u30CF\u30C3\u30B7\u30E5\u304C\u3042\u308A\u307E\u305B\u3093\u3002 -AddHashValuesToDatabaseProgressDialog.addHashValuesToDatabase.success={0}\u30CF\u30C3\u30B7\u30E5\u304C\u6B63\u3057\u304F\u8FFD\u52A0\u3055\u308C\u307E\u3057\u305F\u3002 -AddHashValuesToDatabaseProgressDialog.addHashValuesToDatabase.errorAddingValidHash=\u6709\u52B9\u306A\u30CF\u30C3\u30B7\u30E5\u3092\u8FFD\u52A0\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002 -AddHashValuesToDatabaseProgressDialog.addHashValuesToDatabase.errorAddingValidHash.msg=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306B\u6709\u52B9\u306A\u30CF\u30C3\u30B7\u30E5\u3092\u8FFD\u52A0\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002 -HashLookupSettingsPanel.addHashesToDatabaseButton.text=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306B\u30CF\u30C3\u30B7\u30E5\u3092\u8FFD\u52A0 +AddHashValuesToDatabaseProgressDialog.statusLabel.text=\u30b9\u30c6\u30fc\u30bf\u30b9 +AddHashValuesToDatabaseProgressDialog.title=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30d7\u30ed\u30b0\u30ec\u30b9\u306b\u30cf\u30c3\u30b7\u30e5\u3092\u8ffd\u52a0 +AddHashValuesToDatabaseDialog.title=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306b\u30cf\u30c3\u30b7\u30e5\u3092\u8ffd\u52a0 +AddHashValuesToDatabaseProgressDialog.showErrorsButton.text=\u30a8\u30e9\u30fc\u3092\u8868\u793a +AddHashValuesToDatabaseProgressDialog.addHashValuesToDatabase.parsing=MD5\u30cf\u30c3\u30b7\u30e5\u306b\u30c6\u30ad\u30b9\u30c8\u3092\u30d1\u30fc\u30b9\u4e2d... +AddHashValuesToDatabaseProgressDialog.addHashValuesToDatabase.invalidHash=\u30a4\u30f3\u30d7\u30c3\u30c8\u306b\u7121\u52b9\u306a\u30cf\u30c3\u30b7\u30e5\u304c\u542b\u307e\u308c\u3066\u3044\u307e\u3059\u3002 +AddHashValuesToDatabaseProgressDialog.addHashValuesToDatabase.invaliHash.msg=\u7121\u52b9\u306a\u30cf\u30c3\u30b7\u30e5\uff1a +AddHashValuesToDatabaseProgressDialog.addHashValuesToDatabase.noHashesToAdd=\u8ffd\u52a0\u3059\u308b\u30cf\u30c3\u30b7\u30e5\u304c\u3042\u308a\u307e\u305b\u3093\u3002 +AddHashValuesToDatabaseProgressDialog.addHashValuesToDatabase.success={0}\u30cf\u30c3\u30b7\u30e5\u304c\u6b63\u3057\u304f\u8ffd\u52a0\u3055\u308c\u307e\u3057\u305f\u3002 +AddHashValuesToDatabaseProgressDialog.addHashValuesToDatabase.errorAddingValidHash=\u6709\u52b9\u306a\u30cf\u30c3\u30b7\u30e5\u3092\u8ffd\u52a0\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +AddHashValuesToDatabaseProgressDialog.addHashValuesToDatabase.errorAddingValidHash.msg=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306b\u6709\u52b9\u306a\u30cf\u30c3\u30b7\u30e5\u3092\u8ffd\u52a0\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +HashLookupSettingsPanel.addHashesToDatabaseButton.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306b\u30cf\u30c3\u30b7\u30e5\u3092\u8ffd\u52a0 diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java index 7ceea59224..b544e41120 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java @@ -30,6 +30,7 @@ import javax.swing.JFileChooser; import javax.swing.JOptionPane; import javax.swing.JFrame; import org.apache.commons.io.FilenameUtils; +import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb.KnownFilesType; @@ -46,6 +47,7 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { .getMessage(HashDbCreateDatabaseDialog.class, "HashDbCreateDatabaseDialog.defaultFileName"); private JFileChooser fileChooser = null; private HashDb newHashDb = null; + private final static String LAST_FILE_PATH_KEY = "HashDbCreate_Path"; /** * Displays a dialog that allows a user to create a new hash database and @@ -273,17 +275,23 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { private void saveAsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveAsButtonActionPerformed try { + String lastBaseDirectory = ""; + if (ModuleSettings.settingExists(ModuleSettings.MAIN_SETTINGS, LAST_FILE_PATH_KEY)) { + lastBaseDirectory = ModuleSettings.getConfigSetting(ModuleSettings.MAIN_SETTINGS, LAST_FILE_PATH_KEY); + } StringBuilder path = new StringBuilder(); + path.append(lastBaseDirectory); if (!hashSetNameTextField.getText().isEmpty()) { - path.append(hashSetNameTextField.getText()); + path.append(File.separator).append(hashSetNameTextField.getText()); } else { - path.append(DEFAULT_FILE_NAME); + path.append(File.separator).append(DEFAULT_FILE_NAME); } path.append(".").append(HashDbManager.getHashDatabaseFileExtension()); fileChooser.setSelectedFile(new File(path.toString())); if (fileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) { File databaseFile = fileChooser.getSelectedFile(); databasePathTextField.setText(databaseFile.getCanonicalPath()); + ModuleSettings.setConfigSetting(ModuleSettings.MAIN_SETTINGS, LAST_FILE_PATH_KEY, databaseFile.getParent()); } } catch (IOException ex) { Logger.getLogger(HashDbCreateDatabaseDialog.class.getName()).log(Level.WARNING, "Couldn't get selected file path.", ex); //NON-NLS diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java index 24b389e398..43205b7f6b 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java @@ -32,6 +32,7 @@ import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.JFrame; import org.sleuthkit.datamodel.TskCoreException; import org.apache.commons.io.FilenameUtils; +import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb.KnownFilesType; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDbManagerException; @@ -46,6 +47,7 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { private JFileChooser fileChooser = new JFileChooser(); private String selectedFilePath = ""; private HashDb selectedHashDb = null; + private final static String LAST_FILE_PATH_KEY = "HashDbImport_Path"; /** * Displays a dialog that allows a user to select an existing hash database @@ -249,6 +251,9 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { }// //GEN-END:initComponents private void openButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openButtonActionPerformed + if (ModuleSettings.settingExists(ModuleSettings.MAIN_SETTINGS, LAST_FILE_PATH_KEY)) { + fileChooser.setCurrentDirectory(new File(ModuleSettings.getConfigSetting(ModuleSettings.MAIN_SETTINGS, LAST_FILE_PATH_KEY))); + } if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { File databaseFile = fileChooser.getSelectedFile(); try { @@ -259,6 +264,7 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { knownRadioButton.setSelected(true); knownRadioButtonActionPerformed(null); } + ModuleSettings.setConfigSetting(ModuleSettings.MAIN_SETTINGS, LAST_FILE_PATH_KEY, databaseFile.getParent()); } catch (IOException ex) { Logger.getLogger(HashDbImportDatabaseDialog.class.getName()).log(Level.SEVERE, "Failed to get path of selected database", ex); //NON-NLS JOptionPane.showMessageDialog(this, diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java index b422ae048e..73c7b089c7 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java @@ -82,8 +82,9 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan }); } + @NbBundle.Messages({"HashLookupSettingsPanel.Title=Global Hash Lookup Settings"}) private void customizeComponents() { - setName(NbBundle.getMessage(this.getClass(), "HashDbConfigPanel.setName.hashSetConfig")); + setName(Bundle.HashLookupSettingsPanel_Title()); this.ingestWarningLabel.setVisible(false); this.hashSetTable.setModel(hashSetTableModel); this.hashSetTable.setTableHeader(null); diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle.properties index 10dbc8140e..3a1ced09a3 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle.properties @@ -6,14 +6,6 @@ OptionsCategory_Name_InterestingItemDefinitions=Interesting Files OptionsCategory_Keywords_InterestingItemDefinitions=InterestingItemDefinitions InterestingItemsIdentifierIngestModule.moduleName=Interesting Files Identifier InterestingItemsIdentifierIngestModule.moduleDescription=Identifies interesting items as defined by interesting item rule sets. -InterestingItemDefsPanel.newSetButton.text=New Set -InterestingItemDefsPanel.editSetButton.text=Edit Set -InterestingItemDefsPanel.deleteSetButton.text=Delete Set -InterestingItemDefsPanel.newRuleButton.text=New Rule -InterestingItemDefsPanel.editRuleButton.text=Edit Rule -InterestingItemDefsPanel.deleteRuleButton.text=Delete Rule -InterestingItemDefsPanel.setsListLabel.text=Rule Sets -InterestingItemDefsPanel.rulesListLabel.text=Rules: FilesSetPanel.title=Interesting Files Set FilesSetPanel.messages.filesSetsMustBeNamed=Interesting files sets must be named. FilesSetPanel.ignoreKnownFilesCheckbox.text=Ignore Known Files @@ -28,37 +20,48 @@ FilesSetRulePanel.fullNameRadioButton.text=Full Name FilesSetRulePanel.nameRegexCheckbox.text=Regex FilesSetRulePanel.ruleNameTextField.text= FilesSetRulePanel.nameTextField.text= -FilesSetRulePanel.ruleNameLabel.text=Rule Name: -FilesSetRulePanel.messages.emptyNameFilter=You must specify a name pattern for this rule. +FilesSetRulePanel.ruleNameLabel.text=Rule Name (Optional): +FilesSetRulePanel.messages.emptyNameCondition=You must specify a name pattern for this rule. FilesSetRulePanel.messages.invalidNameRegex=The name regular expression is not valid:\n\n{0} FilesSetRulePanel.messages.invalidCharInName=The name cannot contain \\, /, :, *, ?, \", <, or > unless it is a regular expression. FilesSetRulePanel.messages.invalidCharInPath=The path cannot contain \\, :, *, ?, \", <, or > unless it is a regular expression. FilesSetRulePanel.messages.invalidPathRegex=The path regular expression is not valid:\n\n{0} -FilesSetRulePanel.dirsRadioButton.text=Directories -FilesSetRulePanel.filesRadioButton.text=Files -InterestingItemDefsPanel.bothRadioButton.text=Files and Directories -InterestingItemDefsPanel.dirsRadioButton.text=Directories -InterestingItemDefsPanel.filesRadioButton.text=Files -InterestingItemDefsPanel.fileNameRegexCheckbox.text=Regex -InterestingItemDefsPanel.fileNameExtensionRadioButton.text=Extension Only -InterestingItemDefsPanel.fileNameTextField.text= -InterestingItemDefsPanel.fileNameRadioButton.text=File Name InterestingItemDefsPanel.doFileSetsDialog.duplicateRuleSet.text=Rule set with name {0} already exists. FilesSetRulePanel.pathSeparatorInfoLabel.text=Use / as path separator -FilesSetRulePanel.filesAndDirsRadioButton.text=Files and Directories -InterestingItemDefsPanel.rulePathFilterTextField.text= -InterestingItemDefsPanel.rulePathFilterRegexCheckBox.text=Regex -InterestingItemDefsPanel.ignoreKnownFilesCheckbox.text=Ignore Known Files FilesIdentifierIngestJobSettingsPanel.border.title=Select interesting files sets to enable during ingest: -InterestingItemDefsPanel.jLabel1.text=Rule Details -InterestingItemDefsPanel.jLabel2.text=File Type: -InterestingItemDefsPanel.jLabel3.text=Name Pattern -InterestingItemDefsPanel.jLabel4.text=Path Pattern: -InterestingItemDefsPanel.jLabel5.text=Description: -InterestingItemDefsPanel.jLabel6.text=Set Details -FilesSetRulePanel.jLabel1.text=Type*\: -FilesSetRulePanel.jLabel2.text=Name Pattern*: -FilesSetRulePanel.jLabel3.text=Path Pattern: -InterestingItemDefsPanel.jTextArea1.text=This module allows you to find files that match specified criteria. Each set has a list of rules, which will match on file name and parent path patterns. -FilesSetRulePanel.jLabel4.text=* Required +FilesSetRulePanel.jLabel1.text=Type: FilesSetRulePanel.jLabel5.text=Enter information about files that you want to find. +InterestingItemDefsPanel.jLabel6.text=Set Details +InterestingItemDefsPanel.jLabel8.text=File Size: +InterestingItemDefsPanel.jLabel7.text=MIME Type: +InterestingItemDefsPanel.jTextArea1.text=This module allows you to find files that match specified criteria. Each set has a list of rules, which will match on file name and parent path patterns. +InterestingItemDefsPanel.jLabel4.text=Path Pattern: +InterestingItemDefsPanel.jLabel1.text=Rule Details +InterestingItemDefsPanel.dirsRadioButton.text=Directories +InterestingItemDefsPanel.jLabel2.text=File Type: +InterestingItemDefsPanel.newSetButton.text=New Set +InterestingItemDefsPanel.deleteRuleButton.text=Delete Rule +InterestingItemDefsPanel.deleteSetButton.text=Delete Set +InterestingItemDefsPanel.bothRadioButton.text=Files and Directories +InterestingItemDefsPanel.setsListLabel.text=Rule Sets +InterestingItemDefsPanel.fileNameRegexCheckbox.text=Regex +InterestingItemDefsPanel.ignoreKnownFilesCheckbox.text=Ignore Known Files +InterestingItemDefsPanel.fileNameRadioButton.text=File Name +InterestingItemDefsPanel.jLabel5.text=Description: +InterestingItemDefsPanel.fileNameTextField.text= +InterestingItemDefsPanel.jLabel3.text=Name Pattern: +InterestingItemDefsPanel.fileNameExtensionRadioButton.text=Extension Only +InterestingItemDefsPanel.editSetButton.text=Edit Set +InterestingItemDefsPanel.rulesListLabel.text=Rules: +InterestingItemDefsPanel.editRuleButton.text=Edit Rule +InterestingItemDefsPanel.filesRadioButton.text=Files +InterestingItemDefsPanel.newRuleButton.text=New Rule +InterestingItemDefsPanel.rulePathConditionTextField.text= +InterestingItemDefsPanel.rulePathConditionRegexCheckBox.text=Regex +FilesSetRulePanel.nameCheck.text=Name Pattern: +FilesSetRulePanel.pathCheck.text=Path Pattern: +FilesSetRulePanel.mimeCheck.text=MIME Type: +FilesSetRulePanel.fileSizeCheck.text=File Size: +FilesSetRulePanel.filesRadioButton.text=Files +FilesSetRulePanel.dirsRadioButton.text=Directories +FilesSetRulePanel.filesAndDirsRadioButton.text=Files and Directories diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle_ja.properties index 90c0f44998..487925a7b4 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle_ja.properties @@ -1,59 +1,74 @@ -FilesIdentifierIngestJobSettingsPanel.border.title=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u4E2D\u306B\u6709\u52B9\u306B\u3059\u308B\u7591\u308F\u3057\u3044\u30D5\u30A1\u30A4\u30EB\u30BB\u30C3\u30C8\u3092\u9078\u629E\uFF1A +FilesIdentifierIngestJobSettingsPanel.border.title=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u4e2d\u306b\u6709\u52b9\u306b\u3059\u308b\u7591\u308f\u3057\u3044\u30d5\u30a1\u30a4\u30eb\u30bb\u30c3\u30c8\u3092\u9078\u629e\uff1a FilesSetPanel.descPanel.border.title=\u6982\u8981 FilesSetPanel.descriptionPanel.border.title=\u6982\u8981 -FilesSetPanel.ignoreKnownFilesCheckbox.text=\u65E2\u77E5\u30D5\u30A1\u30A4\u30EB\u3092\u7121\u8996 -FilesSetPanel.messages.filesSetsMustBeNamed=\u7591\u308F\u3057\u3044\u30D5\u30A1\u30A4\u30EB\u30BB\u30C3\u30C8\u306F\u540D\u524D\u304C\u5FC5\u8981\u3067\u3059\u3002 -FilesSetPanel.nameLabel.text=\u30BB\u30C3\u30C8\u540D\uFF1A -FilesSetPanel.title=\u7591\u308F\u3057\u3044\u30D5\u30A1\u30A4\u30EB\u30BB\u30C3\u30C8 -FilesSetRulePanel.dirsRadioButton.text=\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA -FilesSetRulePanel.extensionRadioButton.text=\u62E1\u5F35\u5B50\u306E\u307F -FilesSetRulePanel.filesAndDirsRadioButton.text=\u30D5\u30A1\u30A4\u30EB\u304A\u3088\u3073\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA -FilesSetRulePanel.filesRadioButton.text=\u30D5\u30A1\u30A4\u30EB -FilesSetRulePanel.fullNameRadioButton.text=\u30D5\u30EB\u30CD\u30FC\u30E0 -FilesSetRulePanel.jLabel1.text=\u30BF\u30A4\u30D7*\uFF1A -FilesSetRulePanel.jLabel2.text=\u30CD\u30FC\u30E0\u30D1\u30BF\u30FC\u30F3*\uFF1A -FilesSetRulePanel.jLabel3.text=\u30D1\u30B9\u30D1\u30BF\u30FC\u30F3\uFF1A -FilesSetRulePanel.messages.emptyNameFilter=\u3053\u306E\u30EB\u30FC\u30EB\u306F\u30CD\u30FC\u30E0\u30D1\u30BF\u30FC\u30F3\u3092\u7279\u5B9A\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002 -FilesSetRulePanel.messages.invalidCharInName=\u6B63\u898F\u8868\u73FE\u4EE5\u5916\u306F\\\u3001/\u3001\:\u3001*\u3001?\u3001"\u3001<\u3001>\u3092\u540D\u524D\u306B\u542B\u3081\u307E\u305B\u3093\u3002 -FilesSetRulePanel.messages.invalidCharInPath=\u6B63\u898F\u8868\u73FE\u4EE5\u5916\u306F\\\u3001\:\u3001*\u3001?\u3001"\u3001<\u3001>\u3092\u30D1\u30B9\u306B\u542B\u3081\u307E\u305B\u3093\u3002 -FilesSetRulePanel.messages.invalidNameRegex=\u6B63\u898F\u8868\u73FE\u306F\u6709\u52B9\u306A\u540D\u524D\u3067\u306F\u3042\u308A\u307E\u305B\u3093\uFF1A\n\n{0} -FilesSetRulePanel.messages.invalidPathRegex=\u6B63\u898F\u8868\u73FE\u306F\u6709\u52B9\u306A\u30D1\u30B9\u3067\u306F\u3042\u308A\u307E\u305B\u3093\uFF1A\n\n{0} -FilesSetRulePanel.nameRegexCheckbox.text=\u6B63\u898F\u8868\u73FE -FilesSetRulePanel.pathRegexCheckBox.text=\u6B63\u898F\u8868\u73FE -FilesSetRulePanel.pathSeparatorInfoLabel.text=/\u3092\u30D1\u30B9\u533A\u5207\u308A\u6587\u5B57\u3068\u3057\u3066\u5229\u7528 -FilesSetRulePanel.ruleNameLabel.text=\u30EB\u30FC\u30EB\u540D\uFF1A -FilesSetRulePanel.title=\u7591\u308F\u3057\u3044\u30D5\u30A1\u30A4\u30EB\u30BB\u30C3\u30C8\u30EB\u30FC\u30EB -InterestingItemDefsPanel.bothRadioButton.text=\u30D5\u30A1\u30A4\u30EB\u304A\u3088\u3073\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA -InterestingItemDefsPanel.deleteRuleButton.text=\u30EB\u30FC\u30EB\u3092\u524A\u9664 -InterestingItemDefsPanel.deleteSetButton.text=\u30BB\u30C3\u30C8\u3092\u524A\u9664 -InterestingItemDefsPanel.dirsRadioButton.text=\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA -InterestingItemDefsPanel.editRuleButton.text=\u30EB\u30FC\u30EB\u3092\u7DE8\u96C6 -InterestingItemDefsPanel.editSetButton.text=\u30BB\u30C3\u30C8\u3092\u7DE8\u96C6 -InterestingItemDefsPanel.fileNameExtensionRadioButton.text=\u62E1\u5F35\u5B50\u306E\u307F -InterestingItemDefsPanel.fileNameRadioButton.text=\u30D5\u30A1\u30A4\u30EB\u540D -InterestingItemDefsPanel.fileNameRegexCheckbox.text=\u6B63\u898F\u8868\u73FE -InterestingItemDefsPanel.filesRadioButton.text=\u30D5\u30A1\u30A4\u30EB -InterestingItemDefsPanel.ignoreKnownFilesCheckbox.text=\u65E2\u77E5\u30D5\u30A1\u30A4\u30EB\u3092\u7121\u8996 -InterestingItemDefsPanel.jLabel1.text=\u30EB\u30FC\u30EB\u8A73\u7D30 -InterestingItemDefsPanel.jLabel2.text=\u30D5\u30A1\u30A4\u30EB\u30BF\u30A4\u30D7\uFF1A -InterestingItemDefsPanel.jLabel3.text=\u30CD\u30FC\u30E0\u30D1\u30BF\u30FC\u30F3 -InterestingItemDefsPanel.jLabel4.text=\u30D1\u30B9\u30D1\u30BF\u30FC\u30F3\uFF1A -InterestingItemDefsPanel.jLabel5.text=\u6982\u8981\uFF1A -InterestingItemDefsPanel.jLabel6.text=\u30BB\u30C3\u30C8\u8A73\u7D30 -InterestingItemDefsPanel.jTextArea1.text=\u6307\u5B9A\u3055\u308C\u305F\u6761\u4EF6\u3068\u4E00\u81F4\u3059\u308B\u30D5\u30A1\u30A4\u30EB\u3092\u691C\u7D22\u3059\u308B\u306E\u304C\u53EF\u80FD\u306A\u30E2\u30B8\u30E5\u30FC\u30EB\u3067\u3059\u3002\u5404\u30BB\u30C3\u30C8\u306B\u306F\u30D5\u30A1\u30A4\u30EB\u540D\u304A\u3088\u3073\u30DA\u30A2\u30EC\u30F3\u30C8\u30D1\u30B9\u30D1\u30BF\u30FC\u30F3\u3092\u3082\u3068\u306B\u4E00\u81F4\u3059\u308B\u3001\u30EB\u30FC\u30EB\u30EA\u30B9\u30C8\u304C\u3042\u308A\u307E\u3059\u3002 -InterestingItemDefsPanel.newRuleButton.text=\u65B0\u898F\u30EB\u30FC\u30EB -InterestingItemDefsPanel.newSetButton.text=\u65B0\u898F\u30BB\u30C3\u30C8 -InterestingItemDefsPanel.rulePathFilterRegexCheckBox.text=\u6B63\u898F\u8868\u73FE -InterestingItemDefsPanel.rulesListLabel.text=\u30EB\u30FC\u30EB\uFF1A -InterestingItemDefsPanel.setsListLabel.text=\u30EB\u30FC\u30EB\u30BB\u30C3\u30C8 -InterestingItemsIdentifierIngestModule.moduleDescription=\u7591\u308F\u3057\u3044\u30A2\u30A4\u30C6\u30E0\u30EB\u30FC\u30EB\u30BB\u30C3\u30C8\u306E\u5B9A\u7FA9\u3092\u3082\u3068\u306B\u7591\u308F\u3057\u3044\u30A2\u30A4\u30C6\u30E0\u3092\u691C\u77E5\u3057\u307E\u3059\u3002 -InterestingItemsIdentifierIngestModule.moduleName=\u7591\u308F\u3057\u3044\u30D5\u30A1\u30A4\u30EB\u691C\u77E5 -OpenIDE-Module-Display-Category=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB -OpenIDE-Module-Long-Description=\u7591\u308F\u3057\u3044\u30D5\u30A1\u30A4\u30EB\u691C\u77E5\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u3002\n\n\u7591\u308F\u3057\u3044\u30D5\u30A1\u30A4\u30EB\u30EB\u30FC\u30EB\u30BB\u30C3\u30C8\u306E\u5B9A\u7FA9\u3092\u3082\u3068\u306B\u7591\u308F\u3057\u3044\u30D5\u30A1\u30A4\u30EB\u3092\u691C\u77E5\u3057\u307E\u3059\u3002 -OpenIDE-Module-Name=\u7591\u308F\u3057\u3044\u30D5\u30A1\u30A4\u30EB\u691C\u77E5 -OpenIDE-Module-Short-Description=\u7591\u308F\u3057\u3044\u30D5\u30A1\u30A4\u30EB\u691C\u77E5\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB -OptionsCategory_Name_InterestingItemDefinitions=\u7591\u308F\u3057\u3044\u30D5\u30A1\u30A4\u30EB -OptionsCategory_Keywords_InterestingItemDefinitions=\u7591\u308F\u3057\u3044\u30A2\u30A4\u30C6\u30E0\u5B9A\u7FA9 -InterestingItemDefsPanel.doFileSetsDialog.duplicateRuleSet.text=\u540D\u524D\u304C{0}\u306E\u30EB\u30FC\u30EB\u30BB\u30C3\u30C8\u306F\u65E2\u306B\u5B58\u5728\u3057\u307E\u3059\u3002 -FilesSetRulePanel.jLabel4.text=*\u5FC5\u9808 -FilesSetRulePanel.jLabel5.text=\u898B\u3064\u3051\u305F\u3044\u30D5\u30A1\u30A4\u30EB\u306E\u60C5\u5831\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044\u3002 \ No newline at end of file +FilesSetPanel.ignoreKnownFilesCheckbox.text=\u65e2\u77e5\u30d5\u30a1\u30a4\u30eb\u3092\u7121\u8996 +FilesSetPanel.messages.filesSetsMustBeNamed=\u7591\u308f\u3057\u3044\u30d5\u30a1\u30a4\u30eb\u30bb\u30c3\u30c8\u306f\u540d\u524d\u304c\u5fc5\u8981\u3067\u3059\u3002 +FilesSetPanel.nameLabel.text=\u30bb\u30c3\u30c8\u540d\uff1a +FilesSetPanel.title=\u7591\u308f\u3057\u3044\u30d5\u30a1\u30a4\u30eb\u30bb\u30c3\u30c8 +FilesSetRulePanel.extensionRadioButton.text=\u62e1\u5f35\u5b50\u306e\u307f +FilesSetRulePanel.fullNameRadioButton.text=\u30d5\u30eb\u30cd\u30fc\u30e0 +FilesSetRulePanel.jLabel1.text=\u30bf\u30a4\u30d7*\uff1a +FilesSetRulePanel.messages.emptyNameCondition=\u3053\u306e\u30eb\u30fc\u30eb\u306f\u30cd\u30fc\u30e0\u30d1\u30bf\u30fc\u30f3\u3092\u7279\u5b9a\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 +FilesSetRulePanel.messages.invalidCharInName=\u6b63\u898f\u8868\u73fe\u4ee5\u5916\u306f\\\u3001/\u3001\:\u3001*\u3001?\u3001"\u3001<\u3001>\u3092\u540d\u524d\u306b\u542b\u3081\u307e\u305b\u3093\u3002 +FilesSetRulePanel.messages.invalidCharInPath=\u6b63\u898f\u8868\u73fe\u4ee5\u5916\u306f\\\u3001\:\u3001*\u3001?\u3001"\u3001<\u3001>\u3092\u30d1\u30b9\u306b\u542b\u3081\u307e\u305b\u3093\u3002 +FilesSetRulePanel.messages.invalidNameRegex=\u6b63\u898f\u8868\u73fe\u306f\u6709\u52b9\u306a\u540d\u524d\u3067\u306f\u3042\u308a\u307e\u305b\u3093\uff1a\n\n{0} +FilesSetRulePanel.messages.invalidPathRegex=\u6b63\u898f\u8868\u73fe\u306f\u6709\u52b9\u306a\u30d1\u30b9\u3067\u306f\u3042\u308a\u307e\u305b\u3093\uff1a\n\n{0} +FilesSetRulePanel.nameRegexCheckbox.text=\u6b63\u898f\u8868\u73fe +FilesSetRulePanel.pathRegexCheckBox.text=\u6b63\u898f\u8868\u73fe +FilesSetRulePanel.pathSeparatorInfoLabel.text=/\u3092\u30d1\u30b9\u533a\u5207\u308a\u6587\u5b57\u3068\u3057\u3066\u5229\u7528 +FilesSetRulePanel.ruleNameLabel.text=\u30eb\u30fc\u30eb\u540d\uff1a +FilesSetRulePanel.title=\u7591\u308f\u3057\u3044\u30d5\u30a1\u30a4\u30eb\u30bb\u30c3\u30c8\u30eb\u30fc\u30eb +InterestingItemsIdentifierIngestModule.moduleDescription=\u7591\u308f\u3057\u3044\u30a2\u30a4\u30c6\u30e0\u30eb\u30fc\u30eb\u30bb\u30c3\u30c8\u306e\u5b9a\u7fa9\u3092\u3082\u3068\u306b\u7591\u308f\u3057\u3044\u30a2\u30a4\u30c6\u30e0\u3092\u691c\u77e5\u3057\u307e\u3059\u3002 +InterestingItemsIdentifierIngestModule.moduleName=\u7591\u308f\u3057\u3044\u30d5\u30a1\u30a4\u30eb\u691c\u77e5 +OpenIDE-Module-Display-Category=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb +OpenIDE-Module-Long-Description=\u7591\u308f\u3057\u3044\u30d5\u30a1\u30a4\u30eb\u691c\u77e5\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3002\n\n\u7591\u308f\u3057\u3044\u30d5\u30a1\u30a4\u30eb\u30eb\u30fc\u30eb\u30bb\u30c3\u30c8\u306e\u5b9a\u7fa9\u3092\u3082\u3068\u306b\u7591\u308f\u3057\u3044\u30d5\u30a1\u30a4\u30eb\u3092\u691c\u77e5\u3057\u307e\u3059\u3002 +OpenIDE-Module-Name=\u7591\u308f\u3057\u3044\u30d5\u30a1\u30a4\u30eb\u691c\u77e5 +OpenIDE-Module-Short-Description=\u7591\u308f\u3057\u3044\u30d5\u30a1\u30a4\u30eb\u691c\u77e5\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb +OptionsCategory_Name_InterestingItemDefinitions=\u7591\u308f\u3057\u3044\u30d5\u30a1\u30a4\u30eb +OptionsCategory_Keywords_InterestingItemDefinitions=\u7591\u308f\u3057\u3044\u30a2\u30a4\u30c6\u30e0\u5b9a\u7fa9 +InterestingItemDefsPanel.doFileSetsDialog.duplicateRuleSet.text=\u540d\u524d\u304c{0}\u306e\u30eb\u30fc\u30eb\u30bb\u30c3\u30c8\u306f\u65e2\u306b\u5b58\u5728\u3057\u307e\u3059\u3002 +FilesSetRulePanel.jLabel5.text=\u898b\u3064\u3051\u305f\u3044\u30d5\u30a1\u30a4\u30eb\u306e\u60c5\u5831\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +InterestingItemDefsPanel.jTextArea1.text=\u6307\u5b9a\u3055\u308c\u305f\u6761\u4ef6\u3068\u4e00\u81f4\u3059\u308b\u30d5\u30a1\u30a4\u30eb\u3092\u691c\u7d22\u3059\u308b\u306e\u304c\u53ef\u80fd\u306a\u30e2\u30b8\u30e5\u30fc\u30eb\u3067\u3059\u3002\u5404\u30bb\u30c3\u30c8\u306b\u306f\u30d5\u30a1\u30a4\u30eb\u540d\u304a\u3088\u3073\u30da\u30a2\u30ec\u30f3\u30c8\u30d1\u30b9\u30d1\u30bf\u30fc\u30f3\u3092\u3082\u3068\u306b\u4e00\u81f4\u3059\u308b\u3001\u30eb\u30fc\u30eb\u30ea\u30b9\u30c8\u304c\u3042\u308a\u307e\u3059\u3002 + +InterestingItemDefsPanel.jLabel4.text=\u30d1\u30b9\u30d1\u30bf\u30fc\u30f3\uff1a + +InterestingItemDefsPanel.jLabel1.text=\u30eb\u30fc\u30eb\u8a73\u7d30 + +InterestingItemDefsPanel.dirsRadioButton.text=\u30c7\u30a3\u30ec\u30af\u30c8\u30ea + +InterestingItemDefsPanel.jLabel2.text=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\uff1a + +InterestingItemDefsPanel.newSetButton.text=\u65b0\u898f\u30bb\u30c3\u30c8 + +InterestingItemDefsPanel.deleteRuleButton.text=\u30eb\u30fc\u30eb\u3092\u524a\u9664 + +InterestingItemDefsPanel.deleteSetButton.text=\u30bb\u30c3\u30c8\u3092\u524a\u9664 + +InterestingItemDefsPanel.bothRadioButton.text=\u30d5\u30a1\u30a4\u30eb\u304a\u3088\u3073\u30c7\u30a3\u30ec\u30af\u30c8\u30ea + +InterestingItemDefsPanel.setsListLabel.text=\u30eb\u30fc\u30eb\u30bb\u30c3\u30c8 + +InterestingItemDefsPanel.fileNameRegexCheckbox.text=\u6b63\u898f\u8868\u73fe + +InterestingItemDefsPanel.ignoreKnownFilesCheckbox.text=\u65e2\u77e5\u30d5\u30a1\u30a4\u30eb\u3092\u7121\u8996 + +InterestingItemDefsPanel.fileNameRadioButton.text=\u30d5\u30a1\u30a4\u30eb\u540d + +InterestingItemDefsPanel.jLabel5.text=\u6982\u8981\uff1a + +InterestingItemDefsPanel.jLabel3.text=\u30cd\u30fc\u30e0\u30d1\u30bf\u30fc\u30f3 + +InterestingItemDefsPanel.fileNameExtensionRadioButton.text=\u62e1\u5f35\u5b50\u306e\u307f + +InterestingItemDefsPanel.editSetButton.text=\u30bb\u30c3\u30c8\u3092\u7de8\u96c6 + +InterestingItemDefsPanel.rulesListLabel.text=\u30eb\u30fc\u30eb\uff1a + +InterestingItemDefsPanel.editRuleButton.text=\u30eb\u30fc\u30eb\u3092\u7de8\u96c6 + +InterestingItemDefsPanel.filesRadioButton.text=\u30d5\u30a1\u30a4\u30eb + +InterestingItemDefsPanel.newRuleButton.text=\u65b0\u898f\u30eb\u30fc\u30eb + +InterestingItemDefsPanel.jLabel6.text=\u30bb\u30c3\u30c8\u8a73\u7d30 +InterestingItemDefsPanel.rulePathConditionRegexCheckBox.text=\u6b63\u898f\u8868\u73fe diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestJobSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestJobSettingsPanel.java index a9a17c984e..261b23a3da 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestJobSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestJobSettingsPanel.java @@ -26,6 +26,9 @@ import java.util.TreeMap; import javax.swing.JTable; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableColumn; +import org.openide.util.Exceptions; +import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel; @@ -33,6 +36,10 @@ import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel; * Ingest job settings panel for interesting files identifier ingest modules. */ final class FilesIdentifierIngestJobSettingsPanel extends IngestModuleIngestJobSettingsPanel implements Observer { + @Messages({ + "FilesIdentifierIngestJobSettingsPanel.updateError=Error updating interesting files sets settings file.", + "FilesIdentifierIngestJobSettingsPanel.getError=Error getting interesting files sets from settings file." + }) private final FilesSetsTableModel tableModel; @@ -75,7 +82,12 @@ final class FilesIdentifierIngestJobSettingsPanel extends IngestModuleIngestJobS * Observer.update(). */ List filesSetRows = new ArrayList<>(); - this.filesSetSnapshot = new TreeMap<>(InterestingItemDefsManager.getInstance().getInterestingFilesSets()); + try { + this.filesSetSnapshot = new TreeMap<>(InterestingItemDefsManager.getInstance().getInterestingFilesSets()); + } catch (InterestingItemDefsManager.InterestingItemDefsManagerException ex) { + MessageNotifyUtil.Message.error(Bundle.FilesIdentifierIngestJobSettingsPanel_getError()); + this.filesSetSnapshot = new TreeMap<>(); + } for (FilesSet set : this.filesSetSnapshot.values()) { filesSetRows.add(new FilesSetRow(set, settings.interestingFilesSetIsEnabled(set.getName()))); } @@ -130,7 +142,13 @@ final class FilesIdentifierIngestJobSettingsPanel extends IngestModuleIngestJobS // Refresh the view of the interesting files set definitions. List rowModels = new ArrayList<>(); - TreeMap newFilesSetSnapshot = new TreeMap<>(InterestingItemDefsManager.getInstance().getInterestingFilesSets()); + TreeMap newFilesSetSnapshot; + try { + newFilesSetSnapshot = new TreeMap<>(InterestingItemDefsManager.getInstance().getInterestingFilesSets()); + } catch (InterestingItemDefsManager.InterestingItemDefsManagerException ex) { + MessageNotifyUtil.Message.error(Bundle.FilesIdentifierIngestJobSettingsPanel_updateError()); + return; + } for (FilesSet set : newFilesSetSnapshot.values()) { if (this.filesSetSnapshot.keySet().contains(set.getName())) { // Preserve the current enabled/diabled state of the set. diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestModule.java index ae93cbbc74..03fb011e48 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestModule.java @@ -24,7 +24,9 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; +import org.openide.util.Exceptions; import org.openide.util.NbBundle; +import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.services.Blackboard; import org.sleuthkit.autopsy.coreutils.Logger; @@ -44,6 +46,9 @@ import org.sleuthkit.datamodel.TskCoreException; * files that match interesting files set definitions. */ final class FilesIdentifierIngestModule implements FileIngestModule { + @Messages({ + "FilesIdentifierIngestModule.getFilesError=Error getting interesting files sets from file." + }) private static final Object sharedResourcesLock = new Object(); private static final Logger logger = Logger.getLogger(FilesIdentifierIngestModule.class.getName()); @@ -77,10 +82,14 @@ final class FilesIdentifierIngestModule implements FileIngestModule { // synchronized definitions manager method eliminates the need // to disable the interesting files set definition UI during ingest. List filesSets = new ArrayList<>(); - for (FilesSet set : InterestingItemDefsManager.getInstance().getInterestingFilesSets().values()) { - if (settings.interestingFilesSetIsEnabled(set.getName())) { - filesSets.add(set); + try { + for (FilesSet set : InterestingItemDefsManager.getInstance().getInterestingFilesSets().values()) { + if (settings.interestingFilesSetIsEnabled(set.getName())) { + filesSets.add(set); + } } + } catch (InterestingItemDefsManager.InterestingItemDefsManagerException ex) { + throw new IngestModuleException(Bundle.FilesIdentifierIngestModule_getFilesError(), ex); } FilesIdentifierIngestModule.interestingFileSetsByJob.put(context.getJobId(), filesSets); } diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSet.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSet.java index a1fb1fff66..f207e720d2 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSet.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSet.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.modules.interestingitems; +import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -35,8 +36,9 @@ import org.sleuthkit.datamodel.TskData; * Interesting files set definition objects are immutable, so they may be safely * published to multiple threads. */ -final class FilesSet { +final class FilesSet implements Serializable { + private static final long serialVersionUID = 1L; private final String name; private final String description; private final boolean ignoreKnownFiles; @@ -135,51 +137,65 @@ final class FilesSet { * A set membership rule for an interesting files set. The immutability of a * rule object allows it to be safely published to multiple threads. */ - static class Rule { + static class Rule implements Serializable { + private static final long serialVersionUID = 1L; private final String uuid; private final String ruleName; - private final FileNameFilter fileNameFilter; - private final MetaTypeFilter metaTypeFilter; - private final ParentPathFilter pathFilter; - private final List filters = new ArrayList<>(); + private final FileNameCondition fileNameCondition; + private final MetaTypeCondition metaTypeCondition; + private final ParentPathCondition pathCondition; + private final MimeTypeCondition mimeTypeCondition; + private final FileSizeCondition fileSizeCondition; + private final List conditions = new ArrayList<>(); /** * Construct an interesting files set membership rule. * - * @param ruleName The name of the rule. - * @param fileNameFilter A file name filter. - * @param metaTypeFilter A file meta-type filter. - * @param pathFilter A file path filter, may be null. + * @param ruleName The name of the rule. Can be empty string. + * @param fileNameCondition A file name condition, may be null. + * @param metaTypeCondition A file meta-type condition. + * @param pathCondition A file path condition, may be null. + * @param mimeTypeCondition A file mime type condition, may be null. + * @param fileSizeCondition A file size condition, may be null. */ - Rule(String ruleName, FileNameFilter fileNameFilter, MetaTypeFilter metaTypeFilter, ParentPathFilter pathFilter) { + Rule(String ruleName, FileNameCondition fileNameCondition, MetaTypeCondition metaTypeCondition, ParentPathCondition pathCondition, MimeTypeCondition mimeTypeCondition, FileSizeCondition fileSizeCondition) { // since ruleName is optional, ruleUUID can be used to uniquely identify a rule. this.uuid = UUID.randomUUID().toString(); + if (metaTypeCondition == null) { + throw new IllegalArgumentException("Interesting files set rule meta-type condition cannot be null"); + } + if (pathCondition == null && fileNameCondition == null && mimeTypeCondition == null && fileSizeCondition == null) { + throw new IllegalArgumentException("Must have at least one condition on rule."); + } - if (ruleName == null) { - throw new IllegalArgumentException("Interesting files set rule name cannot be null"); - } - if (fileNameFilter == null) { - throw new IllegalArgumentException("Interesting files set rule file name filter cannot be null"); - } - if (metaTypeFilter == null) { - throw new IllegalArgumentException("Interesting files set rule meta-type filter cannot be null"); - } this.ruleName = ruleName; /* * The rules are evaluated in the order added. MetaType check is * fastest, so do it first */ - this.metaTypeFilter = metaTypeFilter; - this.filters.add(this.metaTypeFilter); + this.metaTypeCondition = metaTypeCondition; + this.conditions.add(this.metaTypeCondition); - this.fileNameFilter = fileNameFilter; - this.filters.add(fileNameFilter); + this.fileSizeCondition = fileSizeCondition; + if (this.fileSizeCondition != null) { + this.conditions.add(this.fileSizeCondition); + } - this.pathFilter = pathFilter; - if (this.pathFilter != null) { - this.filters.add(this.pathFilter); + this.fileNameCondition = fileNameCondition; + if (this.fileNameCondition != null) { + this.conditions.add(fileNameCondition); + } + + this.mimeTypeCondition = mimeTypeCondition; + if (this.mimeTypeCondition != null) { + this.conditions.add(mimeTypeCondition); + } + + this.pathCondition = pathCondition; + if (this.pathCondition != null) { + this.conditions.add(this.pathCondition); } } @@ -193,30 +209,30 @@ final class FilesSet { } /** - * Get the file name filter for the rule. + * Get the file name condition for the rule. * - * @return A file name filter. + * @return A file name condition. Can be null. */ - FileNameFilter getFileNameFilter() { - return this.fileNameFilter; + FileNameCondition getFileNameCondition() { + return this.fileNameCondition; } /** - * Get the meta-type filter for the rule. + * Get the meta-type condition for the rule. * - * @return A meta-type filter. + * @return A meta-type condition. Can be null. */ - MetaTypeFilter getMetaTypeFilter() { - return this.metaTypeFilter; + MetaTypeCondition getMetaTypeCondition() { + return this.metaTypeCondition; } /** - * Get the path filter for the rule. + * Get the path condition for the rule. * - * @return A path filter, may be null. + * @return A path condition, may be null. */ - ParentPathFilter getPathFilter() { - return this.pathFilter; + ParentPathCondition getPathCondition() { + return this.pathCondition; } /** @@ -227,8 +243,8 @@ final class FilesSet { * @return True if the rule is satisfied, false otherwise. */ boolean isSatisfied(AbstractFile file) { - for (FileAttributeFilter filter : filters) { - if (!filter.passes(file)) { + for (FileAttributeCondition condition : conditions) { + if (!condition.passes(file)) { return false; } } @@ -242,7 +258,19 @@ final class FilesSet { public String toString() { // This override is designed to provide a display name for use with // javax.swing.DefaultListModel. - return this.ruleName + " (" + fileNameFilter.getTextToMatch() + ")"; + if (fileNameCondition != null) { + return this.ruleName + " (" + fileNameCondition.getTextToMatch() + ")"; + } else if (this.pathCondition != null) { + return this.ruleName + " (" + pathCondition.getTextToMatch() + ")"; + } else if (this.mimeTypeCondition != null) { + return this.ruleName + " (" + mimeTypeCondition.getMimeType() + ")"; + } else if (this.fileSizeCondition != null) { + return this.ruleName + " (" + fileSizeCondition.getComparator().getSymbol() + " " + fileSizeCondition.getSizeValue() + + " " + fileSizeCondition.getUnit().getName() + ")"; + } else { + return this.ruleName + " ()"; + } + } /** @@ -253,13 +281,27 @@ final class FilesSet { } /** - * An interface for the file attribute filters of which interesting + * @return the mime type condition. Can be null. + */ + MimeTypeCondition getMimeTypeCondition() { + return mimeTypeCondition; + } + + /** + * @return the file size condition. Can be null. + */ + FileSizeCondition getFileSizeCondition() { + return fileSizeCondition; + } + + /** + * An interface for the file attribute conditions of which interesting * files set membership rules are composed. */ - static interface FileAttributeFilter { + static interface FileAttributeCondition extends Serializable { /** - * Tests whether or not a file satisfies the conditions of a filter. + * Tests whether or not a file satisfies the condition. * * @param file The file to test. * @@ -269,11 +311,193 @@ final class FilesSet { } /** - * A file meta-type filter for an interesting files set membership rule. - * The immutability of a meta-type filter object allows it to be safely - * published to multiple threads. + * A class for checking files based upon their MIME types. */ - static final class MetaTypeFilter implements FileAttributeFilter { + static final class MimeTypeCondition implements FileAttributeCondition { + + private static final long serialVersionUID = 1L; + private final String mimeType; + + /** + * Constructs a MimeTypeCondition + * + * @param mimeType The mime type to condition for + */ + MimeTypeCondition(String mimeType) { + this.mimeType = mimeType; + } + + /** + * @inheritDoc + */ + @Override + public boolean passes(AbstractFile file) { + return this.mimeType.equals(file.getMIMEType()); + } + + /** + * Gets the mime type that is being checked + * + * @return the mime type + */ + String getMimeType() { + return this.mimeType; + } + + } + + /** + * A class for checking whether a file's size is within the + * specifications given (i.e. < N Bytes). + */ + static final class FileSizeCondition implements FileAttributeCondition { + + private static final long serialVersionUID = 1L; + + /** + * Represents a comparison item for file size + */ + static enum COMPARATOR { + + LESS_THAN("<"), + LESS_THAN_EQUAL("≤"), + EQUAL("="), + GREATER_THAN(">"), + GREATER_THAN_EQUAL("≥"); + + private String symbol; + + COMPARATOR(String symbol) { + this.symbol = symbol; + } + + public static COMPARATOR fromSymbol(String symbol) { + if (symbol.equals("<=") || symbol.equals("≤")) { + return LESS_THAN_EQUAL; + } else if (symbol.equals("<")) { + return LESS_THAN; + } else if (symbol.equals("==") || symbol.equals("=")) { + return EQUAL; + } else if (symbol.equals(">")) { + return GREATER_THAN; + } else if (symbol.equals(">=") || symbol.equals("≥")) { + return GREATER_THAN_EQUAL; + } else { + throw new IllegalArgumentException("Invalid symbol"); + } + } + + /** + * @return the symbol + */ + public String getSymbol() { + return symbol; + } + } + + /** + * Represents the units of size + */ + static enum SIZE_UNIT { + + BYTE(1, "Bytes"), + KILOBYTE(1024, "Kilobytes"), + MEGABYTE(1024 * 1024, "Megabytes"), + GIGABYTE(1024 * 1024 * 1024, "Gigabytes"); + private long size; + private String name; + + private SIZE_UNIT(long size, String name) { + this.size = size; + this.name = name; + } + + public long getSize() { + return this.size; + } + + public static SIZE_UNIT fromName(String name) { + for (SIZE_UNIT unit : SIZE_UNIT.values()) { + if (unit.getName().equals(name)) { + return unit; + } + } + throw new IllegalArgumentException("Invalid name for size unit."); + } + + /** + * @return the name + */ + public String getName() { + return name; + } + } + private final COMPARATOR comparator; + private final SIZE_UNIT unit; + private final int sizeValue; + + FileSizeCondition(COMPARATOR comparator, SIZE_UNIT unit, int sizeValue) { + this.comparator = comparator; + this.unit = unit; + this.sizeValue = sizeValue; + } + + /** + * Gets the comparator of this condition + * + * @return the comparator + */ + COMPARATOR getComparator() { + return comparator; + } + + /** + * Gets the unit for the size of this condition + * + * @return the unit + */ + SIZE_UNIT getUnit() { + return unit; + } + + /** + * Gets the size value of this condition + * + * @return the size value + */ + int getSizeValue() { + return sizeValue; + } + + @Override + public boolean passes(AbstractFile file) { + long fileSize = file.getSize(); + long conditionSize = this.getUnit().getSize() * this.getSizeValue(); + switch (this.getComparator()) { + case GREATER_THAN: + return fileSize > conditionSize; + case GREATER_THAN_EQUAL: + return fileSize >= conditionSize; + case LESS_THAN_EQUAL: + return fileSize <= conditionSize; + case LESS_THAN: + return fileSize < conditionSize; + default: + return fileSize == conditionSize; + + } + } + + } + + /** + * A file meta-type condition for an interesting files set membership + * rule. The immutability of a meta-type condition object allows it to + * be safely published to multiple threads. + */ + static final class MetaTypeCondition implements FileAttributeCondition { + + private static final long serialVersionUID = 1L; enum Type { @@ -285,11 +509,11 @@ final class FilesSet { private final Type type; /** - * Construct a meta-type filter. + * Construct a meta-type condition. * * @param metaType The meta-type to match, must. */ - MetaTypeFilter(Type type) { + MetaTypeCondition(Type type) { this.type = type; } @@ -310,9 +534,9 @@ final class FilesSet { } /** - * Gets the meta-type the filter matches. + * Gets the meta-type the condition matches. * - * @return A member of the MetaTypeFilter.Type enumeration. + * @return A member of the MetaTypeCondition.Type enumeration. */ Type getMetaType() { return this.type; @@ -320,20 +544,20 @@ final class FilesSet { } /** - * An interface for file attribute filters that do textual matching. + * An interface for file attribute conditions that do textual matching. */ - static interface TextFilter extends FileAttributeFilter { + static interface TextCondition extends FileAttributeCondition { /** - * Gets the text the filter matches. + * Gets the text the condition matches. * * @return The text. */ String getTextToMatch(); /** - * Queries whether or not the text the filter matches is a regular - * expression. + * Queries whether or not the text the condition matches is a + * regular expression. * * @return True if the text to be matched is a regular expression, * false otherwise. @@ -341,7 +565,7 @@ final class FilesSet { boolean isRegex(); /** - * Determines whether a string of text matches the filter. + * Determines whether a string of text matches the condition. * * @param textToMatch The text string. * @@ -352,19 +576,19 @@ final class FilesSet { } /** - * An abstract base class for file attribute filters that do textual + * An abstract base class for file attribute conditions that do textual * matching. */ - private static abstract class AbstractTextFilter implements TextFilter { + private static abstract class AbstractTextCondition implements TextCondition { private final TextMatcher textMatcher; /** - * Construct a case-insensitive text filter. + * Construct a case-insensitive text condition. * * @param text The text to be matched. */ - AbstractTextFilter(String text, Boolean partialMatch) { + AbstractTextCondition(String text, Boolean partialMatch) { if (partialMatch) { this.textMatcher = new FilesSet.Rule.CaseInsensitivePartialStringComparisionMatcher(text); } else { @@ -373,16 +597,16 @@ final class FilesSet { } /** - * Construct a regular expression text filter. + * Construct a regular expression text condition. * * @param regex The regular expression to be matched. */ - AbstractTextFilter(Pattern regex) { + AbstractTextCondition(Pattern regex) { this.textMatcher = new FilesSet.Rule.RegexMatcher(regex); } /** - * Get the text the filter matches. + * Get the text the condition matches. * * @return The text. */ @@ -392,8 +616,8 @@ final class FilesSet { } /** - * Queries whether or not the text the filter matches is a regular - * expression. + * Queries whether or not the text the condition matches is a + * regular expression. * * @return True if the text to be matched is a regular expression, * false otherwise. @@ -404,7 +628,7 @@ final class FilesSet { } /** - * Determines whether a string of text matches the filter. + * Determines whether a string of text matches the condition. * * @param textToMatch The text string. * @@ -424,27 +648,29 @@ final class FilesSet { } /** - * A file path filter for an interesting files set membership rule. The - * immutability of a path filter object allows it to be safely published - * to multiple threads. + * A file path condition for an interesting files set membership rule. + * The immutability of a path condition object allows it to be safely + * published to multiple threads. */ - static final class ParentPathFilter extends AbstractTextFilter { + static final class ParentPathCondition extends AbstractTextCondition { + + private static final long serialVersionUID = 1L; /** - * Construct a case-insensitive file path filter. + * Construct a case-insensitive file path condition. * * @param path The path to be matched. */ - ParentPathFilter(String path) { + ParentPathCondition(String path) { super(path, true); } /** - * Construct a file path regular expression filter. + * Construct a file path regular expression condition. * * @param path The path regular expression to be matched. */ - ParentPathFilter(Pattern path) { + ParentPathCondition(Pattern path) { super(path); } @@ -459,34 +685,37 @@ final class FilesSet { } /** - * A "tagging" interface to group name and extension filters separately - * from path filters for type safety when constructing rules. + * A "tagging" interface to group name and extension conditions + * separately from path conditions for type safety when constructing + * rules. */ - static interface FileNameFilter extends TextFilter { + static interface FileNameCondition extends TextCondition { } /** - * A file name filter for an interesting files set membership rule. The - * immutability of a file name filter object allows it to be safely - * published to multiple threads. + * A file name condition for an interesting files set membership rule. + * The immutability of a file name condition object allows it to be + * safely published to multiple threads. */ - static final class FullNameFilter extends AbstractTextFilter implements FileNameFilter { + static final class FullNameCondition extends AbstractTextCondition implements FileNameCondition { + + private static final long serialVersionUID = 1L; /** - * Construct a case-insensitive full file name filter. + * Construct a case-insensitive full file name condition. * * @param name The file name to be matched. */ - FullNameFilter(String name) { + FullNameCondition(String name) { super(name, false); } /** - * Construct a full file name regular expression filter. + * Construct a full file name regular expression condition. * * @param name The file name regular expression to be matched. */ - FullNameFilter(Pattern name) { + FullNameCondition(Pattern name) { super(name); } @@ -501,18 +730,20 @@ final class FilesSet { } /** - * A file name extension filter for an interesting files set membership - * rule. The immutability of a file name extension filter object allows - * it to be safely published to multiple threads. + * A file name extension condition for an interesting files set + * membership rule. The immutability of a file name extension condition + * object allows it to be safely published to multiple threads. */ - static final class ExtensionFilter extends AbstractTextFilter implements FileNameFilter { + static final class ExtensionCondition extends AbstractTextCondition implements FileNameCondition { + + private static final long serialVersionUID = 1L; /** - * Construct a case-insensitive file name extension filter. + * Construct a case-insensitive file name extension condition. * * @param extension The file name extension to be matched. */ - ExtensionFilter(String extension) { + ExtensionCondition(String extension) { // If there is a leading ".", strip it since // AbstractFile.getFileNameExtension() returns just the // extension chars and not the dot. @@ -520,12 +751,12 @@ final class FilesSet { } /** - * Construct a file name extension regular expression filter. + * Construct a file name extension regular expression condition. * * @param extension The file name extension regular expression to be * matched. */ - ExtensionFilter(Pattern extension) { + ExtensionCondition(Pattern extension) { super(extension.pattern(), false); } @@ -541,9 +772,9 @@ final class FilesSet { /** * An interface for objects that do textual matches, used to compose a - * text filter. + * text condition. */ - private static interface TextMatcher { + private static interface TextMatcher extends Serializable { /** * Get the text the matcher examines. @@ -577,6 +808,7 @@ final class FilesSet { */ private static class CaseInsensitiveStringComparisionMatcher implements TextMatcher { + private static final long serialVersionUID = 1L; private final String textToMatch; /** @@ -620,6 +852,7 @@ final class FilesSet { */ private static class CaseInsensitivePartialStringComparisionMatcher implements TextMatcher { + private static final long serialVersionUID = 1L; private final String textToMatch; private final Pattern pattern; @@ -664,6 +897,7 @@ final class FilesSet { */ private static class RegexMatcher implements TextMatcher { + private static final long serialVersionUID = 1L; private final Pattern regex; /** diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.form b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.form index dbc69c5ac9..72b506199a 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.form +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.form @@ -23,61 +23,82 @@ - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - + + - - + + + + + + + + + - - - - - - + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - + @@ -85,17 +106,17 @@ - + - + - + - + @@ -106,20 +127,31 @@ - + - + - + + + + + + + + + + + + + - @@ -138,6 +170,9 @@
+ + +
@@ -146,17 +181,167 @@ - + + + + + + + + + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -172,6 +357,19 @@ + + + + + + + + + + + + + @@ -185,91 +383,5 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java index f45b4e8287..fba97d318b 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java @@ -18,14 +18,27 @@ */ package org.sleuthkit.autopsy.modules.interestingitems; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; +import java.util.SortedSet; import java.util.logging.Level; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JOptionPane; +import org.apache.tika.mime.MediaType; +import org.apache.tika.mime.MimeTypes; import org.openide.DialogDisplayer; import org.openide.NotifyDescriptor; import org.openide.util.NbBundle; +import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; /** * A panel that allows a user to create and edit interesting files set @@ -33,17 +46,34 @@ import org.sleuthkit.autopsy.coreutils.Logger; */ final class FilesSetRulePanel extends javax.swing.JPanel { + @Messages({ + "FilesSetRulePanel.bytes=Bytes", + "FilesSetRulePanel.kiloBytes=Kilobytes", + "FilesSetRulePanel.megaBytes=Megabytes", + "FilesSetRulePanel.gigaBytes=Gigabytes", + "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", + "FilesSetRulePanel.NoPathError=Path cannot be empty", + "FilesSetRulePanel.ZeroFileSizeError=File size condition value must not be 0 (Unless = is selected)." + }) + + private static final SortedSet mediaTypes = MimeTypes.getDefaultMimeTypes().getMediaTypeRegistry().getTypes(); private static final Logger logger = Logger.getLogger(FilesSetRulePanel.class.getName()); private static final String SLEUTHKIT_PATH_SEPARATOR = "/"; // NON-NLS private static final List ILLEGAL_FILE_NAME_CHARS = InterestingItemDefsManager.getIllegalFileNameChars(); private static final List ILLEGAL_FILE_PATH_CHARS = InterestingItemDefsManager.getIllegalFilePathChars(); + private JButton okButton; + private JButton cancelButton; /** * Constructs a files set rule panel in create rule mode. */ - FilesSetRulePanel() { + FilesSetRulePanel(JButton okButton, JButton cancelButton) { initComponents(); + populateMimeTypesComboBox(); populateComponentsWithDefaultValues(); + this.setButtons(okButton, cancelButton); } /** @@ -51,12 +81,16 @@ final class FilesSetRulePanel extends javax.swing.JPanel { * * @param rule The files set rule to be edited. */ - FilesSetRulePanel(FilesSet.Rule rule) { + FilesSetRulePanel(FilesSet.Rule rule, JButton okButton, JButton cancelButton) { initComponents(); + populateMimeTypesComboBox(); populateRuleNameComponent(rule); - populateTypeFilterComponents(rule); - populateNameFilterComponents(rule); - populatePathFilterComponents(rule); + populateTypeConditionComponents(rule); + populateNameConditionComponents(rule); + populatePathConditionComponents(rule); + populateMimeConditionComponents(rule); + populateSizeConditionComponents(rule); + this.setButtons(okButton, cancelButton); } /** @@ -65,6 +99,40 @@ final class FilesSetRulePanel extends javax.swing.JPanel { private void populateComponentsWithDefaultValues() { this.filesRadioButton.setSelected(true); this.fullNameRadioButton.setSelected(true); + this.equalitySymbolComboBox.setSelectedItem(FilesSet.Rule.FileSizeCondition.COMPARATOR.GREATER_THAN_EQUAL.getSymbol()); + this.fileSizeComboBox.setSelectedItem(FilesSet.Rule.FileSizeCondition.SIZE_UNIT.KILOBYTE.getName()); + this.mimeTypeComboBox.setSelectedIndex(0); + } + + private void populateMimeTypesComboBox() { + Set fileTypesCollated = new HashSet<>(); + for (MediaType mediaType : mediaTypes) { + fileTypesCollated.add(mediaType.toString()); + } + + FileTypeDetector fileTypeDetector; + try { + fileTypeDetector = new FileTypeDetector(); + List userDefinedFileTypes = fileTypeDetector.getUserDefinedTypes(); + fileTypesCollated.addAll(userDefinedFileTypes); + + } catch (FileTypeDetector.FileTypeDetectorInitException ex) { + logger.log(Level.SEVERE, "Unable to get user defined file types", ex); + } + + List toSort = new ArrayList<>(fileTypesCollated); + toSort.sort((String string1, String string2) -> { + int result = String.CASE_INSENSITIVE_ORDER.compare(string1, string2); + if (result == 0) { + result = string1.compareTo(string2); + } + return result; + }); + + for (String file : toSort) { + mimeTypeComboBox.addItem(file); + } + this.setOkButton(); } /** @@ -76,14 +144,88 @@ final class FilesSetRulePanel extends javax.swing.JPanel { this.ruleNameTextField.setText(rule.getName()); } + private void populateMimeConditionComponents(FilesSet.Rule rule) { + FilesSet.Rule.MimeTypeCondition mimeTypeCondition = rule.getMimeTypeCondition(); + if (mimeTypeCondition != null) { + this.mimeCheck.setSelected(true); + this.mimeCheckActionPerformed(null); + this.mimeTypeComboBox.setSelectedItem(mimeTypeCondition.getMimeType()); + } + } + private void populateSizeConditionComponents(FilesSet.Rule rule) { + FilesSet.Rule.FileSizeCondition fileSizeCondition = rule.getFileSizeCondition(); + if (fileSizeCondition != null) { + this.fileSizeCheck.setSelected(true); + this.fileSizeCheckActionPerformed(null); + this.fileSizeSpinner.setValue(fileSizeCondition.getSizeValue()); + this.fileSizeComboBox.setSelectedItem(fileSizeCondition.getUnit().getName()); + this.equalitySymbolComboBox.setSelectedItem(fileSizeCondition.getComparator().getSymbol()); + } + } + /** - * Populates the UI components that display the meta-type filter for a rule. + * Sets whether or not the OK button should be enabled based upon other UI + * elements + */ + private void setOkButton() { + if (this.okButton != null) { + this.okButton.setEnabled(this.fileSizeCheck.isSelected() || this.mimeCheck.isSelected() + || this.nameCheck.isSelected() || this.pathCheck.isSelected()); + } + } + + /** + * Gets the JOptionPane that is used to contain this panel if there is one + * + * @param parent + * + * @return + */ + private JOptionPane getOptionPane(JComponent parent) { + JOptionPane pane = null; + if (!(parent instanceof JOptionPane)) { + pane = getOptionPane((JComponent) parent.getParent()); + } else { + pane = (JOptionPane) parent; + } + return pane; + } + + /** + * Sets the buttons for ending the panel + * + * @param ok The ok button + * @param cancel The cancel button + */ + private void setButtons(JButton ok, JButton cancel) { + this.okButton = ok; + this.cancelButton = cancel; + okButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + JOptionPane pane = getOptionPane(okButton); + pane.setValue(okButton); + } + }); + cancelButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + JOptionPane pane = getOptionPane(cancelButton); + pane.setValue(cancelButton); + } + }); + this.setOkButton(); + } + + /** + * Populates the UI components that display the meta-type condition for a + * rule. * * @param rule The files set rule to be edited. */ - private void populateTypeFilterComponents(FilesSet.Rule rule) { - FilesSet.Rule.MetaTypeFilter typeFilter = rule.getMetaTypeFilter(); - switch (typeFilter.getMetaType()) { + private void populateTypeConditionComponents(FilesSet.Rule rule) { + FilesSet.Rule.MetaTypeCondition typeCondition = rule.getMetaTypeCondition(); + switch (typeCondition.getMetaType()) { case FILES: this.filesRadioButton.setSelected(true); break; @@ -97,32 +239,38 @@ final class FilesSetRulePanel extends javax.swing.JPanel { } /** - * Populates the UI components that display the name filter for a rule. + * Populates the UI components that display the name condition for a rule. * * @param rule The files set rule to be edited. */ - private void populateNameFilterComponents(FilesSet.Rule rule) { - FilesSet.Rule.FileNameFilter nameFilter = rule.getFileNameFilter(); - this.nameTextField.setText(nameFilter.getTextToMatch()); - this.nameRegexCheckbox.setSelected(nameFilter.isRegex()); - if (nameFilter instanceof FilesSet.Rule.FullNameFilter) { - this.fullNameRadioButton.setSelected(true); - } else { - this.extensionRadioButton.setSelected(true); + private void populateNameConditionComponents(FilesSet.Rule rule) { + FilesSet.Rule.FileNameCondition nameCondition = rule.getFileNameCondition(); + if (nameCondition != null) { + this.nameCheck.setSelected(true); + this.nameCheckActionPerformed(null); + this.nameTextField.setText(nameCondition.getTextToMatch()); + this.nameRegexCheckbox.setSelected(nameCondition.isRegex()); + if (nameCondition instanceof FilesSet.Rule.FullNameCondition) { + this.fullNameRadioButton.setSelected(true); + } else { + this.extensionRadioButton.setSelected(true); + } } } /** - * Populates the UI components that display the optional path filter for a - * rule. + * Populates the UI components that display the optional path condition for + * a rule. * * @param rule The files set rule to be edited. */ - private void populatePathFilterComponents(FilesSet.Rule rule) { - FilesSet.Rule.ParentPathFilter pathFilter = rule.getPathFilter(); - if (pathFilter != null) { - this.pathTextField.setText(pathFilter.getTextToMatch()); - this.pathRegexCheckBox.setSelected(pathFilter.isRegex()); + private void populatePathConditionComponents(FilesSet.Rule rule) { + FilesSet.Rule.ParentPathCondition pathCondition = rule.getPathCondition(); + if (pathCondition != null) { + this.pathCheck.setSelected(true); + this.pathCheckActionPerformed(null); + this.pathTextField.setText(pathCondition.getTextToMatch()); + this.pathRegexCheckBox.setSelected(pathCondition.isRegex()); } } @@ -135,40 +283,55 @@ final class FilesSetRulePanel extends javax.swing.JPanel { */ boolean isValidRuleDefinition() { - // The rule must have name filter text. - if (this.nameTextField.getText().isEmpty()) { + if (!(this.mimeCheck.isSelected() || this.fileSizeCheck.isSelected() || this.pathCheck.isSelected() || this.nameCheck.isSelected())) { NotifyDescriptor notifyDesc = new NotifyDescriptor.Message( - NbBundle.getMessage(FilesSetPanel.class, "FilesSetRulePanel.messages.emptyNameFilter"), + Bundle.FilesSetRulePanel_NoConditionError(), NotifyDescriptor.WARNING_MESSAGE); DialogDisplayer.getDefault().notify(notifyDesc); return false; } - // The name filter must either be a regular expression that compiles or - // a string without illegal file name chars. - if (this.nameRegexCheckbox.isSelected()) { - try { - Pattern.compile(this.nameTextField.getText()); - } catch (PatternSyntaxException ex) { + if (this.nameCheck.isSelected()) { + // The name condition must either be a regular expression that compiles or + // a string without illegal file name chars. + if (this.nameTextField.getText().isEmpty()) { NotifyDescriptor notifyDesc = new NotifyDescriptor.Message( - NbBundle.getMessage(FilesSetPanel.class, "FilesSetRulePanel.messages.invalidNameRegex", ex.getLocalizedMessage()), + Bundle.FilesSetRulePanel_NoNameError(), NotifyDescriptor.WARNING_MESSAGE); DialogDisplayer.getDefault().notify(notifyDesc); return false; } - } else { - if (!FilesSetRulePanel.containsOnlyLegalChars(this.nameTextField.getText(), FilesSetRulePanel.ILLEGAL_FILE_NAME_CHARS)) { - NotifyDescriptor notifyDesc = new NotifyDescriptor.Message( - NbBundle.getMessage(FilesSetPanel.class, "FilesSetRulePanel.messages.invalidCharInName"), - NotifyDescriptor.WARNING_MESSAGE); - DialogDisplayer.getDefault().notify(notifyDesc); - return false; + if (this.nameRegexCheckbox.isSelected()) { + try { + Pattern.compile(this.nameTextField.getText()); + } catch (PatternSyntaxException ex) { + NotifyDescriptor notifyDesc = new NotifyDescriptor.Message( + NbBundle.getMessage(FilesSetPanel.class, "FilesSetRulePanel.messages.invalidNameRegex", ex.getLocalizedMessage()), + NotifyDescriptor.WARNING_MESSAGE); + DialogDisplayer.getDefault().notify(notifyDesc); + return false; + } + } else { + if (this.nameTextField.getText().isEmpty() || !FilesSetRulePanel.containsOnlyLegalChars(this.nameTextField.getText(), FilesSetRulePanel.ILLEGAL_FILE_NAME_CHARS)) { + NotifyDescriptor notifyDesc = new NotifyDescriptor.Message( + NbBundle.getMessage(FilesSetPanel.class, "FilesSetRulePanel.messages.invalidCharInName"), + NotifyDescriptor.WARNING_MESSAGE); + DialogDisplayer.getDefault().notify(notifyDesc); + return false; + } } } - // The path filter, if specified, must either be a regular expression - // that compiles or a string without illegal file path chars. - if (!this.pathTextField.getText().isEmpty()) { + // The path condition, if specified, must either be a regular expression + // that compiles or a string without illegal file path chars. + if (this.pathCheck.isSelected()) { + if (this.pathTextField.getText().isEmpty()) { + NotifyDescriptor notifyDesc = new NotifyDescriptor.Message( + Bundle.FilesSetRulePanel_NoPathError(), + NotifyDescriptor.WARNING_MESSAGE); + DialogDisplayer.getDefault().notify(notifyDesc); + return false; + } if (this.pathRegexCheckBox.isSelected()) { try { Pattern.compile(this.pathTextField.getText()); @@ -180,7 +343,7 @@ final class FilesSetRulePanel extends javax.swing.JPanel { return false; } } else { - if (!FilesSetRulePanel.containsOnlyLegalChars(this.pathTextField.getText(), FilesSetRulePanel.ILLEGAL_FILE_PATH_CHARS)) { + if (this.pathTextField.getText().isEmpty() || !FilesSetRulePanel.containsOnlyLegalChars(this.pathTextField.getText(), FilesSetRulePanel.ILLEGAL_FILE_PATH_CHARS)) { NotifyDescriptor notifyDesc = new NotifyDescriptor.Message( NbBundle.getMessage(FilesSetPanel.class, "FilesSetRulePanel.messages.invalidCharInPath"), NotifyDescriptor.WARNING_MESSAGE); @@ -189,6 +352,24 @@ final class FilesSetRulePanel extends javax.swing.JPanel { } } } + if (this.mimeCheck.isSelected()) { + if (this.mimeTypeComboBox.getSelectedIndex() == 0) { + NotifyDescriptor notifyDesc = new NotifyDescriptor.Message( + Bundle.FilesSetRulePanel_NoMimeTypeError(), + NotifyDescriptor.WARNING_MESSAGE); + DialogDisplayer.getDefault().notify(notifyDesc); + return false; + } + } + if (this.fileSizeCheck.isSelected()) { + if ((Integer) this.fileSizeSpinner.getValue() == 0 && !((String)this.equalitySymbolComboBox.getSelectedItem()).equals("=")) { + NotifyDescriptor notifyDesc = new NotifyDescriptor.Message( + Bundle.FilesSetRulePanel_ZeroFileSizeError(), + NotifyDescriptor.WARNING_MESSAGE); + DialogDisplayer.getDefault().notify(notifyDesc); + return false; + } + } return true; } @@ -203,76 +384,108 @@ final class FilesSetRulePanel extends javax.swing.JPanel { } /** - * Gets the name filter for the rule that was created or edited. Should only - * be called if isValidDefintion() returns true. + * Gets the name condition for the rule that was created or edited. Should + * only be called if isValidDefintion() returns true. * - * @return A name filter. + * @return A name condition. * - * @throws IllegalStateException if the specified name filter is not valid. + * @throws IllegalStateException if the specified name condition is not + * valid. */ - FilesSet.Rule.FileNameFilter getFileNameFilter() throws IllegalStateException { - FilesSet.Rule.FileNameFilter filter = null; + FilesSet.Rule.FileNameCondition getFileNameCondition() throws IllegalStateException { + FilesSet.Rule.FileNameCondition condition = null; if (!this.nameTextField.getText().isEmpty()) { if (this.nameRegexCheckbox.isSelected()) { try { Pattern pattern = Pattern.compile(this.nameTextField.getText()); if (this.fullNameRadioButton.isSelected()) { - filter = new FilesSet.Rule.FullNameFilter(pattern); + condition = new FilesSet.Rule.FullNameCondition(pattern); } else { - filter = new FilesSet.Rule.ExtensionFilter(pattern); + condition = new FilesSet.Rule.ExtensionCondition(pattern); } } catch (PatternSyntaxException ex) { - logger.log(Level.SEVERE, "Attempt to get regex name filter that does not compile", ex); // NON-NLS - throw new IllegalStateException("The files set rule panel name filter is not in a valid state"); // NON-NLS + logger.log(Level.SEVERE, "Attempt to get regex name condition that does not compile", ex); // NON-NLS + throw new IllegalStateException("The files set rule panel name condition is not in a valid state"); // NON-NLS } } else { if (FilesSetRulePanel.containsOnlyLegalChars(this.nameTextField.getText(), FilesSetRulePanel.ILLEGAL_FILE_NAME_CHARS)) { if (this.fullNameRadioButton.isSelected()) { - filter = new FilesSet.Rule.FullNameFilter(this.nameTextField.getText()); + condition = new FilesSet.Rule.FullNameCondition(this.nameTextField.getText()); } else { - filter = new FilesSet.Rule.ExtensionFilter(this.nameTextField.getText()); + condition = new FilesSet.Rule.ExtensionCondition(this.nameTextField.getText()); } } else { - logger.log(Level.SEVERE, "Attempt to get name filter with illegal chars"); // NON-NLS - throw new IllegalStateException("The files set rule panel name filter is not in a valid state"); // NON-NLS + logger.log(Level.SEVERE, "Attempt to get name condition with illegal chars"); // NON-NLS + throw new IllegalStateException("The files set rule panel name condition is not in a valid state"); // NON-NLS } } } - return filter; + return condition; } /** - * Gets the file meta-type filter for the rule that was created or edited. + * Gets the mime type condition based upon the panel input * - * @return A type filter. + * @return the mime type condition, null if no condition is specified */ - FilesSet.Rule.MetaTypeFilter getMetaTypeFilter() { + FilesSet.Rule.MimeTypeCondition getMimeTypeCondition() { + FilesSet.Rule.MimeTypeCondition condition = null; + if (!this.mimeTypeComboBox.getSelectedItem().equals("")) { + condition = new FilesSet.Rule.MimeTypeCondition((String) this.mimeTypeComboBox.getSelectedItem()); + } + return condition; + } + + /** + * Gets the file size condition created based upon the panel input + * + * @return the file size condition, null if no condition is specified + */ + FilesSet.Rule.FileSizeCondition getFileSizeCondition() { + FilesSet.Rule.FileSizeCondition condition = null; + if ((Integer) this.fileSizeSpinner.getValue() != 0 || ((String)this.equalitySymbolComboBox.getSelectedItem()).equals("=")) { + FilesSet.Rule.FileSizeCondition.COMPARATOR comparator = FilesSet.Rule.FileSizeCondition.COMPARATOR.fromSymbol((String) this.equalitySymbolComboBox.getSelectedItem()); + FilesSet.Rule.FileSizeCondition.SIZE_UNIT unit = FilesSet.Rule.FileSizeCondition.SIZE_UNIT.fromName((String) this.fileSizeComboBox.getSelectedItem()); + int fileSizeValue = (Integer) this.fileSizeSpinner.getValue(); + condition = new FilesSet.Rule.FileSizeCondition(comparator, unit, fileSizeValue); + } + return condition; + } + + /** + * Gets the file meta-type condition for the rule that was created or + * edited. + * + * @return A type condition. + */ + FilesSet.Rule.MetaTypeCondition getMetaTypeCondition() { if (this.filesRadioButton.isSelected()) { - return new FilesSet.Rule.MetaTypeFilter(FilesSet.Rule.MetaTypeFilter.Type.FILES); + return new FilesSet.Rule.MetaTypeCondition(FilesSet.Rule.MetaTypeCondition.Type.FILES); } else if (this.dirsRadioButton.isSelected()) { - return new FilesSet.Rule.MetaTypeFilter(FilesSet.Rule.MetaTypeFilter.Type.DIRECTORIES); + return new FilesSet.Rule.MetaTypeCondition(FilesSet.Rule.MetaTypeCondition.Type.DIRECTORIES); } else { - return new FilesSet.Rule.MetaTypeFilter(FilesSet.Rule.MetaTypeFilter.Type.FILES_AND_DIRECTORIES); + return new FilesSet.Rule.MetaTypeCondition(FilesSet.Rule.MetaTypeCondition.Type.FILES_AND_DIRECTORIES); } } /** - * Gets the optional path filter for the rule that was created or edited. + * Gets the optional path condition for the rule that was created or edited. * Should only be called if isValidDefintion() returns true. * - * @return A path filter or null if no path filter was specified. + * @return A path condition or null if no path condition was specified. * - * @throws IllegalStateException if the specified path filter is not valid. + * @throws IllegalStateException if the specified path condition is not + * valid. */ - FilesSet.Rule.ParentPathFilter getPathFilter() throws IllegalStateException { - FilesSet.Rule.ParentPathFilter filter = null; + FilesSet.Rule.ParentPathCondition getPathCondition() throws IllegalStateException { + FilesSet.Rule.ParentPathCondition condition = null; if (!this.pathTextField.getText().isEmpty()) { if (this.pathRegexCheckBox.isSelected()) { try { - filter = new FilesSet.Rule.ParentPathFilter(Pattern.compile(this.pathTextField.getText())); + condition = new FilesSet.Rule.ParentPathCondition(Pattern.compile(this.pathTextField.getText())); } catch (PatternSyntaxException ex) { - logger.log(Level.SEVERE, "Attempt to get malformed path filter", ex); // NON-NLS - throw new IllegalStateException("The files set rule panel path filter is not in a valid state"); // NON-NLS + logger.log(Level.SEVERE, "Attempt to get malformed path condition", ex); // NON-NLS + throw new IllegalStateException("The files set rule panel path condition is not in a valid state"); // NON-NLS } } else { String path = this.pathTextField.getText(); @@ -285,14 +498,14 @@ final class FilesSetRulePanel extends javax.swing.JPanel { if (!path.endsWith(FilesSetRulePanel.SLEUTHKIT_PATH_SEPARATOR)) { path += FilesSetRulePanel.SLEUTHKIT_PATH_SEPARATOR; } - filter = new FilesSet.Rule.ParentPathFilter(path); + condition = new FilesSet.Rule.ParentPathCondition(path); } else { - logger.log(Level.SEVERE, "Attempt to get path filter with illegal chars"); // NON-NLS - throw new IllegalStateException("The files set rule panel path filter is not in a valid state"); // NON-NLS + logger.log(Level.SEVERE, "Attempt to get path condition with illegal chars"); // NON-NLS + throw new IllegalStateException("The files set rule panel path condition is not in a valid state"); // NON-NLS } } } - return filter; + return condition; } /** @@ -314,15 +527,28 @@ final class FilesSetRulePanel extends javax.swing.JPanel { } /** - * Sets the state of the name filter UI components consistent with the state - * of the UI components in the type button group. + * Sets the state of the name condition UI components consistent with the + * state of the UI components in the type button group. */ private void setComponentsForSearchType() { if (!this.filesRadioButton.isSelected()) { this.fullNameRadioButton.setSelected(true); this.extensionRadioButton.setEnabled(false); + this.mimeTypeComboBox.setEnabled(false); + this.mimeTypeComboBox.setSelectedIndex(0); + this.equalitySymbolComboBox.setEnabled(false); + this.fileSizeComboBox.setEnabled(false); + this.fileSizeSpinner.setEnabled(false); + this.fileSizeSpinner.setValue(0); + this.fileSizeCheck.setEnabled(false); + this.fileSizeCheck.setSelected(false); + this.mimeCheck.setEnabled(false); + this.mimeCheck.setSelected(false); + } else { this.extensionRadioButton.setEnabled(true); + this.fileSizeCheck.setEnabled(true); + this.mimeCheck.setEnabled(true); } } @@ -340,32 +566,106 @@ final class FilesSetRulePanel extends javax.swing.JPanel { ruleNameLabel = new javax.swing.JLabel(); ruleNameTextField = new javax.swing.JTextField(); jLabel1 = new javax.swing.JLabel(); - dirsRadioButton = new javax.swing.JRadioButton(); - filesRadioButton = new javax.swing.JRadioButton(); - filesAndDirsRadioButton = new javax.swing.JRadioButton(); - jLabel2 = new javax.swing.JLabel(); nameTextField = new javax.swing.JTextField(); fullNameRadioButton = new javax.swing.JRadioButton(); extensionRadioButton = new javax.swing.JRadioButton(); nameRegexCheckbox = new javax.swing.JCheckBox(); - jLabel3 = new javax.swing.JLabel(); pathTextField = new javax.swing.JTextField(); pathRegexCheckBox = new javax.swing.JCheckBox(); pathSeparatorInfoLabel = new javax.swing.JLabel(); - jLabel4 = new javax.swing.JLabel(); jLabel5 = new javax.swing.JLabel(); + mimeTypeComboBox = new javax.swing.JComboBox(); + equalitySymbolComboBox = new javax.swing.JComboBox(); + fileSizeComboBox = new javax.swing.JComboBox(); + fileSizeSpinner = new javax.swing.JSpinner(); + nameCheck = new javax.swing.JCheckBox(); + pathCheck = new javax.swing.JCheckBox(); + mimeCheck = new javax.swing.JCheckBox(); + fileSizeCheck = new javax.swing.JCheckBox(); + filesRadioButton = new javax.swing.JRadioButton(); + dirsRadioButton = new javax.swing.JRadioButton(); + filesAndDirsRadioButton = new javax.swing.JRadioButton(); org.openide.awt.Mnemonics.setLocalizedText(ruleNameLabel, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.ruleNameLabel.text")); // NOI18N ruleNameTextField.setText(org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.ruleNameTextField.text")); // NOI18N + ruleNameTextField.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + ruleNameTextFieldActionPerformed(evt); + } + }); org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.jLabel1.text")); // NOI18N - typeButtonGroup.add(dirsRadioButton); - org.openide.awt.Mnemonics.setLocalizedText(dirsRadioButton, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.dirsRadioButton.text")); // NOI18N - dirsRadioButton.addActionListener(new java.awt.event.ActionListener() { + nameTextField.setText(org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.nameTextField.text")); // NOI18N + nameTextField.setEnabled(false); + + 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) { - dirsRadioButtonActionPerformed(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); + + org.openide.awt.Mnemonics.setLocalizedText(nameRegexCheckbox, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.nameRegexCheckbox.text")); // NOI18N + nameRegexCheckbox.setEnabled(false); + + pathTextField.setText(org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.pathTextField.text")); // NOI18N + pathTextField.setEnabled(false); + + org.openide.awt.Mnemonics.setLocalizedText(pathRegexCheckBox, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.pathRegexCheckBox.text")); // NOI18N + pathRegexCheckBox.setEnabled(false); + + pathSeparatorInfoLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/info-icon-16.png"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(pathSeparatorInfoLabel, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.pathSeparatorInfoLabel.text")); // NOI18N + pathSeparatorInfoLabel.setEnabled(false); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel5, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.jLabel5.text")); // NOI18N + + mimeTypeComboBox.setEditable(true); + mimeTypeComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] {""})); + mimeTypeComboBox.setEnabled(false); + + equalitySymbolComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "=", ">", "≥", "<", "≤" })); + equalitySymbolComboBox.setEnabled(false); + + fileSizeComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { Bundle.FilesSetRulePanel_bytes(), Bundle.FilesSetRulePanel_kiloBytes(), Bundle.FilesSetRulePanel_megaBytes(), Bundle.FilesSetRulePanel_gigaBytes() })); + fileSizeComboBox.setEnabled(false); + + fileSizeSpinner.setModel(new javax.swing.SpinnerNumberModel(Integer.valueOf(0), Integer.valueOf(0), null, Integer.valueOf(1))); + fileSizeSpinner.setEnabled(false); + + org.openide.awt.Mnemonics.setLocalizedText(nameCheck, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.nameCheck.text")); // NOI18N + nameCheck.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + nameCheckActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(pathCheck, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.pathCheck.text")); // NOI18N + pathCheck.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + pathCheckActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(mimeCheck, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.mimeCheck.text")); // NOI18N + mimeCheck.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + mimeCheckActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(fileSizeCheck, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.fileSizeCheck.text")); // NOI18N + fileSizeCheck.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + fileSizeCheckActionPerformed(evt); } }); @@ -377,6 +677,14 @@ final class FilesSetRulePanel extends javax.swing.JPanel { } }); + typeButtonGroup.add(dirsRadioButton); + org.openide.awt.Mnemonics.setLocalizedText(dirsRadioButton, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.dirsRadioButton.text")); // NOI18N + dirsRadioButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + dirsRadioButtonActionPerformed(evt); + } + }); + typeButtonGroup.add(filesAndDirsRadioButton); org.openide.awt.Mnemonics.setLocalizedText(filesAndDirsRadioButton, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.filesAndDirsRadioButton.text")); // NOI18N filesAndDirsRadioButton.addActionListener(new java.awt.event.ActionListener() { @@ -385,93 +693,85 @@ final class FilesSetRulePanel extends javax.swing.JPanel { } }); - org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.jLabel2.text")); // NOI18N - - nameTextField.setText(org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.nameTextField.text")); // NOI18N - - nameButtonGroup.add(fullNameRadioButton); - org.openide.awt.Mnemonics.setLocalizedText(fullNameRadioButton, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.fullNameRadioButton.text")); // NOI18N - - nameButtonGroup.add(extensionRadioButton); - org.openide.awt.Mnemonics.setLocalizedText(extensionRadioButton, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.extensionRadioButton.text")); // NOI18N - - org.openide.awt.Mnemonics.setLocalizedText(nameRegexCheckbox, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.nameRegexCheckbox.text")); // NOI18N - - org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.jLabel3.text")); // NOI18N - - pathTextField.setText(org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.pathTextField.text")); // NOI18N - - org.openide.awt.Mnemonics.setLocalizedText(pathRegexCheckBox, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.pathRegexCheckBox.text")); // NOI18N - - pathSeparatorInfoLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/info-icon-16.png"))); // NOI18N NON-NLS - org.openide.awt.Mnemonics.setLocalizedText(pathSeparatorInfoLabel, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.pathSeparatorInfoLabel.text")); // NOI18N - - org.openide.awt.Mnemonics.setLocalizedText(jLabel4, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.jLabel4.text")); // NOI18N - - org.openide.awt.Mnemonics.setLocalizedText(jLabel5, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.jLabel5.text")); // NOI18N - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addGroup(layout.createSequentialGroup() - .addComponent(jLabel3) - .addGap(18, 18, 18) + .addGap(8, 8, 8) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(ruleNameLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(ruleNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 234, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel5) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel1) + .addGap(65, 65, 65) + .addComponent(filesRadioButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(dirsRadioButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(filesAndDirsRadioButton))) + .addGap(0, 0, Short.MAX_VALUE)))) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(nameCheck) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(nameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 249, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() + .addContainerGap() + .addComponent(pathCheck) + .addGap(4, 4, 4) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(pathRegexCheckBox) - .addGap(45, 45, 45) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(pathSeparatorInfoLabel)) - .addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 239, javax.swing.GroupLayout.PREFERRED_SIZE))) - .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addComponent(ruleNameLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 59, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(18, 18, 18)) + .addGap(0, 0, Short.MAX_VALUE) + .addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 250, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGroup(layout.createSequentialGroup() - .addComponent(jLabel1) - .addGap(27, 27, 27))) + .addComponent(fullNameRadioButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(extensionRadioButton, javax.swing.GroupLayout.PREFERRED_SIZE, 114, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(nameRegexCheckbox) + .addGap(0, 0, Short.MAX_VALUE)))) + .addGroup(layout.createSequentialGroup() + .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(mimeCheck) + .addComponent(fileSizeCheck)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addGroup(layout.createSequentialGroup() - .addComponent(filesRadioButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(dirsRadioButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(filesAndDirsRadioButton)) - .addComponent(ruleNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 248, javax.swing.GroupLayout.PREFERRED_SIZE))) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() - .addComponent(jLabel2) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(nameTextField)) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() - .addGap(78, 78, 78) - .addComponent(fullNameRadioButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(extensionRadioButton, javax.swing.GroupLayout.PREFERRED_SIZE, 114, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(nameRegexCheckbox))) - .addComponent(jLabel4) - .addComponent(jLabel5)) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addComponent(equalitySymbolComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 36, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(18, 18, 18) + .addComponent(fileSizeSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, 94, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(18, 18, 18) + .addComponent(fileSizeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 82, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(mimeTypeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 250, javax.swing.GroupLayout.PREFERRED_SIZE)))) + .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(jLabel5) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED, 19, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel1) - .addComponent(dirsRadioButton) .addComponent(filesRadioButton) + .addComponent(dirsRadioButton) .addComponent(filesAndDirsRadioButton)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGap(5, 5, 5) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(jLabel2) - .addComponent(nameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(nameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(nameCheck)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(fullNameRadioButton) @@ -480,46 +780,123 @@ final class FilesSetRulePanel extends javax.swing.JPanel { .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(jLabel3)) + .addComponent(pathCheck)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(pathSeparatorInfoLabel) - .addComponent(pathRegexCheckBox)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(pathRegexCheckBox) + .addComponent(pathSeparatorInfoLabel)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 8, Short.MAX_VALUE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(mimeTypeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(mimeCheck)) + .addGap(11, 11, 11) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(equalitySymbolComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(fileSizeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(fileSizeSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(fileSizeCheck)) + .addGap(15, 15, 15) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(ruleNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(ruleNameLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jLabel4)) + .addContainerGap()) ); }// //GEN-END:initComponents - private void filesAndDirsRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_filesAndDirsRadioButtonActionPerformed - setComponentsForSearchType(); - }//GEN-LAST:event_filesAndDirsRadioButtonActionPerformed + private void ruleNameTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ruleNameTextFieldActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_ruleNameTextFieldActionPerformed - private void dirsRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dirsRadioButtonActionPerformed - setComponentsForSearchType(); - }//GEN-LAST:event_dirsRadioButtonActionPerformed + private void nameCheckActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nameCheckActionPerformed + if (!this.nameCheck.isSelected()) { + this.nameTextField.setEnabled(false); + this.nameTextField.setText(""); + this.fullNameRadioButton.setEnabled(false); + this.extensionRadioButton.setEnabled(false); + this.nameRegexCheckbox.setEnabled(false); + } else { + this.nameTextField.setEnabled(true); + this.fullNameRadioButton.setEnabled(true); + this.extensionRadioButton.setEnabled(true); + this.nameRegexCheckbox.setEnabled(true); + } + this.setOkButton(); + }//GEN-LAST:event_nameCheckActionPerformed + + private void pathCheckActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pathCheckActionPerformed + if (!this.pathCheck.isSelected()) { + this.pathTextField.setEnabled(false); + this.pathTextField.setText(""); + this.pathRegexCheckBox.setEnabled(false); + this.pathSeparatorInfoLabel.setEnabled(false); + } else { + this.pathTextField.setEnabled(true); + this.pathRegexCheckBox.setEnabled(true); + this.pathSeparatorInfoLabel.setEnabled(true); + } + this.setOkButton(); + }//GEN-LAST:event_pathCheckActionPerformed + + private void mimeCheckActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mimeCheckActionPerformed + if (!this.mimeCheck.isSelected()) { + this.mimeTypeComboBox.setEnabled(false); + this.mimeTypeComboBox.setSelectedIndex(0); + } else { + this.mimeTypeComboBox.setEnabled(true); + } + this.setOkButton(); + }//GEN-LAST:event_mimeCheckActionPerformed + + private void fileSizeCheckActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fileSizeCheckActionPerformed + if (!this.fileSizeCheck.isSelected()) { + this.fileSizeComboBox.setEnabled(false); + this.fileSizeSpinner.setEnabled(false); + this.fileSizeSpinner.setValue(0); + this.equalitySymbolComboBox.setEnabled(false); + } else { + this.fileSizeComboBox.setEnabled(true); + this.fileSizeSpinner.setEnabled(true); + this.equalitySymbolComboBox.setEnabled(true); + } + this.setOkButton(); + }//GEN-LAST:event_fileSizeCheckActionPerformed private void filesRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_filesRadioButtonActionPerformed - setComponentsForSearchType(); + + this.setComponentsForSearchType(); }//GEN-LAST:event_filesRadioButtonActionPerformed + private void dirsRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dirsRadioButtonActionPerformed + this.setComponentsForSearchType(); + }//GEN-LAST:event_dirsRadioButtonActionPerformed + + private void filesAndDirsRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_filesAndDirsRadioButtonActionPerformed + this.setComponentsForSearchType(); + }//GEN-LAST:event_filesAndDirsRadioButtonActionPerformed + + private void fullNameRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fullNameRadioButtonActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_fullNameRadioButtonActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JRadioButton dirsRadioButton; + private javax.swing.JComboBox equalitySymbolComboBox; private javax.swing.JRadioButton extensionRadioButton; + private javax.swing.JCheckBox fileSizeCheck; + private javax.swing.JComboBox fileSizeComboBox; + private javax.swing.JSpinner fileSizeSpinner; private javax.swing.JRadioButton filesAndDirsRadioButton; private javax.swing.JRadioButton filesRadioButton; private javax.swing.JRadioButton fullNameRadioButton; private javax.swing.JLabel jLabel1; - private javax.swing.JLabel jLabel2; - private javax.swing.JLabel jLabel3; - private javax.swing.JLabel jLabel4; private javax.swing.JLabel jLabel5; + private javax.swing.JCheckBox mimeCheck; + private javax.swing.JComboBox mimeTypeComboBox; private javax.swing.ButtonGroup nameButtonGroup; + private javax.swing.JCheckBox nameCheck; private javax.swing.JCheckBox nameRegexCheckbox; private javax.swing.JTextField nameTextField; + private javax.swing.JCheckBox pathCheck; private javax.swing.JCheckBox pathRegexCheckBox; private javax.swing.JLabel pathSeparatorInfoLabel; private javax.swing.JTextField pathTextField; diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsManager.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsManager.java index 781846cabe..20d6c1e5c7 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsManager.java @@ -19,6 +19,9 @@ package org.sleuthkit.autopsy.modules.interestingitems; import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -29,9 +32,8 @@ import java.util.Observable; import java.util.logging.Level; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; +import org.openide.util.io.NbObjectInputStream; +import org.openide.util.io.NbObjectOutputStream; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.coreutils.XMLUtil; @@ -49,8 +51,10 @@ final class InterestingItemDefsManager extends Observable { private static final List ILLEGAL_FILE_NAME_CHARS = Collections.unmodifiableList(new ArrayList<>(Arrays.asList("\\", "/", ":", "*", "?", "\"", "<", ">"))); private static final List ILLEGAL_FILE_PATH_CHARS = Collections.unmodifiableList(new ArrayList<>(Arrays.asList("\\", ":", "*", "?", "\"", "<", ">"))); - private static final String INTERESTING_FILES_SET_DEFS_FILE_NAME = "InterestingFilesSetDefs.xml"; //NON-NLS - private static final String DEFAULT_FILE_SET_DEFS_PATH = PlatformUtil.getUserConfigDirectory() + File.separator + INTERESTING_FILES_SET_DEFS_FILE_NAME; + private static final String LEGACY_FILES_SET_DEFS_FILE_NAME = "InterestingFilesSetDefs.xml"; //NON-NLS + private static final String INTERESTING_FILES_SET_DEFS_SERIALIZATION_NAME = "InterestingFileSets.settings"; + private static final String INTERESTING_FILES_SET_DEFS_SERIALIZATION_PATH = PlatformUtil.getUserConfigDirectory() + File.separator + INTERESTING_FILES_SET_DEFS_SERIALIZATION_NAME; + private static final String LEGACY_FILE_SET_DEFS_PATH = PlatformUtil.getUserConfigDirectory() + File.separator + LEGACY_FILES_SET_DEFS_FILE_NAME; private static InterestingItemDefsManager instance; /** @@ -88,8 +92,8 @@ final class InterestingItemDefsManager extends Observable { * @return A map of interesting files set names to interesting file sets, * possibly empty. */ - synchronized Map getInterestingFilesSets() { - return FilesSetXML.readDefinitionsFile(DEFAULT_FILE_SET_DEFS_PATH); + synchronized Map getInterestingFilesSets() throws InterestingItemDefsManagerException { + return FilesSetXML.readDefinitionsFile(LEGACY_FILE_SET_DEFS_PATH); } /** @@ -99,8 +103,8 @@ final class InterestingItemDefsManager extends Observable { * @param filesSets A mapping of interesting files set names to files sets, * used to enforce unique files set names. */ - synchronized void setInterestingFilesSets(Map filesSets) { - FilesSetXML.writeDefinitionsFile(DEFAULT_FILE_SET_DEFS_PATH, filesSets); + synchronized void setInterestingFilesSets(Map filesSets) throws InterestingItemDefsManagerException { + FilesSetXML.writeDefinitionsFile(INTERESTING_FILES_SET_DEFS_SERIALIZATION_PATH, filesSets); this.setChanged(); this.notifyObservers(); } @@ -130,21 +134,6 @@ final class InterestingItemDefsManager extends Observable { private static final String TYPE_FILTER_VALUE_FILES = "file"; //NON-NLS private static final String TYPE_FILTER_VALUE_DIRS = "dir"; //NON-NLS - // The following tags and attributes are currently specific to the - // Autopsy implementation of interesting files set definitions. Autopsy - // definitions that use these will not be able to be used by TSK - // Framework. However, Autopsy can accept TSK Framework definitions: - // - // 1. Rules do not have names in the TSK Framework schema, but rules do - // have names in the Autopsy schema. Names will be synthesized as needed - // to allow Autopsy to use TSK Framework interesting files set - // definitions. - // 2. The TSK Framework has an interesting files module that supports - // simple globbing with "*" characters. Name rules and path filters with - // "*" characters will be converted to regexes to allow Autopsy to use - // TSK Framework interesting files set definitions. - // 3. Type filters are required by Autopsy, but not by TSK Frmaework. - // Missing type filters will defualt to "files" filters. private static final String REGEX_ATTR = "regex"; //NON-NLS private static final String PATH_REGEX_ATTR = "pathRegex"; //NON-NLS private static final String TYPE_FILTER_VALUE_FILES_AND_DIRS = "files_and_dirs"; //NON-NLS @@ -161,10 +150,13 @@ final class InterestingItemDefsManager extends Observable { // Note: This method takes a file path to support the possibility of // multiple intersting files set definition files, e.g., one for // definitions that ship with Autopsy and one for user definitions. - static Map readDefinitionsFile(String filePath) { - Map filesSets = new HashMap<>(); + static Map readDefinitionsFile(String filePath) throws InterestingItemDefsManagerException { + Map filesSets = readSerializedDefinitions(); - // Check if the file exists. + if (!filesSets.isEmpty()) { + return filesSets; + } + // Check if the legacy xml file exists. File defsFile = new File(filePath); if (!defsFile.exists()) { return filesSets; @@ -195,10 +187,34 @@ final class InterestingItemDefsManager extends Observable { for (int i = 0; i < setElems.getLength(); ++i) { readFilesSet((Element) setElems.item(i), filesSets, filePath); } - return filesSets; } + /** + * Reads the definitions from the serialization file + * + * @return the map representing settings saved to serialization file, + * empty set if the file does not exist. + * + * @throws InterestingItemDefsManagerException if file could not be read + */ + private static Map readSerializedDefinitions() throws InterestingItemDefsManagerException { + String filePath = INTERESTING_FILES_SET_DEFS_SERIALIZATION_PATH; + File fileSetFile = new File(filePath); + if (fileSetFile.exists()) { + try { + try (NbObjectInputStream in = new NbObjectInputStream(new FileInputStream(filePath))) { + InterestingItemsFilesSetSettings filesSetsSettings = (InterestingItemsFilesSetSettings) in.readObject(); + return filesSetsSettings.getFilesSets(); + } + } catch (IOException | ClassNotFoundException ex) { + throw new InterestingItemDefsManagerException(String.format("Failed to read settings from %s", filePath), ex); + } + } else { + return new HashMap(); + } + } + /** * Reads in an interesting files set. * @@ -288,16 +304,16 @@ final class InterestingItemDefsManager extends Observable { private static FilesSet.Rule readFileNameRule(Element elem) { String ruleName = FilesSetXML.readRuleName(elem); - // The content of the rule tag is a file name filter. It may be a + // The content of the rule tag is a file name condition. It may be a // regex, or it may be from a TSK Framework rule definition with a // "*" globbing char, or it may be simple text. String content = elem.getTextContent(); - FilesSet.Rule.FullNameFilter nameFilter; + FilesSet.Rule.FullNameCondition nameCondition; String regex = elem.getAttribute(FilesSetXML.REGEX_ATTR); if ((!regex.isEmpty() && regex.equalsIgnoreCase("true")) || content.contains("*")) { // NON-NLS Pattern pattern = compileRegex(content); if (pattern != null) { - nameFilter = new FilesSet.Rule.FullNameFilter(pattern); + nameCondition = new FilesSet.Rule.FullNameCondition(pattern); } else { logger.log(Level.SEVERE, "Error compiling " + FilesSetXML.NAME_RULE_TAG + " regex, ignoring malformed '{0}' rule definition", ruleName); // NON-NLS return null; @@ -309,29 +325,29 @@ final class InterestingItemDefsManager extends Observable { return null; } } - nameFilter = new FilesSet.Rule.FullNameFilter(content); + nameCondition = new FilesSet.Rule.FullNameCondition(content); } - // Read in the type filter. - FilesSet.Rule.MetaTypeFilter metaTypeFilter = FilesSetXML.readMetaTypeFilter(elem); - if (metaTypeFilter == null) { + // Read in the type condition. + FilesSet.Rule.MetaTypeCondition metaTypeCondition = FilesSetXML.readMetaTypeCondition(elem); + if (metaTypeCondition == null) { // Malformed attribute. return null; } - // Read in the optional path filter. Null is o.k., but if the attribute + // Read in the optional path condition. Null is o.k., but if the attribute // is there, be sure it is not malformed. - FilesSet.Rule.ParentPathFilter pathFilter = null; + FilesSet.Rule.ParentPathCondition pathCondition = null; if (!elem.getAttribute(FilesSetXML.PATH_FILTER_ATTR).isEmpty() || !elem.getAttribute(FilesSetXML.PATH_REGEX_ATTR).isEmpty()) { - pathFilter = FilesSetXML.readPathFilter(elem); - if (pathFilter == null) { + pathCondition = FilesSetXML.readPathCondition(elem); + if (pathCondition == null) { // Malformed attribute. return null; } } - return new FilesSet.Rule(ruleName, nameFilter, metaTypeFilter, pathFilter); + return new FilesSet.Rule(ruleName, nameCondition, metaTypeCondition, pathCondition, null, null); } /** @@ -346,16 +362,16 @@ final class InterestingItemDefsManager extends Observable { private static FilesSet.Rule readFileExtensionRule(Element elem) { String ruleName = FilesSetXML.readRuleName(elem); - // The content of the rule tag is a file name extension filter. It may + // The content of the rule tag is a file name extension condition. It may // be a regex, or it may be from a TSK Framework rule definition // with a "*" globbing char. String content = elem.getTextContent(); - FilesSet.Rule.ExtensionFilter extFilter; + FilesSet.Rule.ExtensionCondition extCondition; String regex = elem.getAttribute(FilesSetXML.REGEX_ATTR); if ((!regex.isEmpty() && regex.equalsIgnoreCase("true")) || content.contains("*")) { // NON-NLS Pattern pattern = compileRegex(content); if (pattern != null) { - extFilter = new FilesSet.Rule.ExtensionFilter(pattern); + extCondition = new FilesSet.Rule.ExtensionCondition(pattern); } else { logger.log(Level.SEVERE, "Error compiling " + FilesSetXML.EXTENSION_RULE_TAG + " regex, ignoring malformed {0} rule definition", ruleName); // NON-NLS return null; @@ -367,35 +383,35 @@ final class InterestingItemDefsManager extends Observable { return null; } } - extFilter = new FilesSet.Rule.ExtensionFilter(content); + extCondition = new FilesSet.Rule.ExtensionCondition(content); } - // The rule must have a meta-type filter, unless a TSK Framework + // The rule must have a meta-type condition, unless a TSK Framework // definitions file is being read. - FilesSet.Rule.MetaTypeFilter metaTypeFilter = null; + FilesSet.Rule.MetaTypeCondition metaTypeCondition = null; if (!elem.getAttribute(FilesSetXML.TYPE_FILTER_ATTR).isEmpty()) { - metaTypeFilter = FilesSetXML.readMetaTypeFilter(elem); - if (metaTypeFilter == null) { + metaTypeCondition = FilesSetXML.readMetaTypeCondition(elem); + if (metaTypeCondition == null) { // Malformed attribute. return null; } } else { - metaTypeFilter = new FilesSet.Rule.MetaTypeFilter(FilesSet.Rule.MetaTypeFilter.Type.FILES); + metaTypeCondition = new FilesSet.Rule.MetaTypeCondition(FilesSet.Rule.MetaTypeCondition.Type.FILES); } - // The rule may have a path filter. Null is o.k., but if the attribute + // The rule may have a path condition. Null is o.k., but if the attribute // is there, it must not be malformed. - FilesSet.Rule.ParentPathFilter pathFilter = null; + FilesSet.Rule.ParentPathCondition pathCondition = null; if (!elem.getAttribute(FilesSetXML.PATH_FILTER_ATTR).isEmpty() || !elem.getAttribute(FilesSetXML.PATH_REGEX_ATTR).isEmpty()) { - pathFilter = FilesSetXML.readPathFilter(elem); - if (pathFilter == null) { + pathCondition = FilesSetXML.readPathCondition(elem); + if (pathCondition == null) { // Malformed attribute. return null; } } - return new FilesSet.Rule(ruleName, extFilter, metaTypeFilter, pathFilter); + return new FilesSet.Rule(ruleName, extCondition, metaTypeCondition, pathCondition, null, null); } /** @@ -428,62 +444,63 @@ final class InterestingItemDefsManager extends Observable { } /** - * Construct a meta-type filter for an interesting files set membership - * rule from data in an XML element. + * Construct a meta-type condition for an interesting files set + * membership rule from data in an XML element. * * @param ruleElement The XML element. * - * @return The meta-type filter, or null if there is an error (logged). + * @return The meta-type condition, or null if there is an error + * (logged). */ - private static FilesSet.Rule.MetaTypeFilter readMetaTypeFilter(Element ruleElement) { - FilesSet.Rule.MetaTypeFilter filter = null; - String filterAttribute = ruleElement.getAttribute(FilesSetXML.TYPE_FILTER_ATTR); - if (!filterAttribute.isEmpty()) { - switch (filterAttribute) { + private static FilesSet.Rule.MetaTypeCondition readMetaTypeCondition(Element ruleElement) { + FilesSet.Rule.MetaTypeCondition condition = null; + String conditionAttribute = ruleElement.getAttribute(FilesSetXML.TYPE_FILTER_ATTR); + if (!conditionAttribute.isEmpty()) { + switch (conditionAttribute) { case FilesSetXML.TYPE_FILTER_VALUE_FILES: - filter = new FilesSet.Rule.MetaTypeFilter(FilesSet.Rule.MetaTypeFilter.Type.FILES); + condition = new FilesSet.Rule.MetaTypeCondition(FilesSet.Rule.MetaTypeCondition.Type.FILES); break; case FilesSetXML.TYPE_FILTER_VALUE_DIRS: - filter = new FilesSet.Rule.MetaTypeFilter(FilesSet.Rule.MetaTypeFilter.Type.DIRECTORIES); + condition = new FilesSet.Rule.MetaTypeCondition(FilesSet.Rule.MetaTypeCondition.Type.DIRECTORIES); break; case FilesSetXML.TYPE_FILTER_VALUE_FILES_AND_DIRS: - filter = new FilesSet.Rule.MetaTypeFilter(FilesSet.Rule.MetaTypeFilter.Type.FILES_AND_DIRECTORIES); + condition = new FilesSet.Rule.MetaTypeCondition(FilesSet.Rule.MetaTypeCondition.Type.FILES_AND_DIRECTORIES); break; default: - logger.log(Level.SEVERE, "Found {0} " + FilesSetXML.TYPE_FILTER_ATTR + " attribute with unrecognized value ''{0}'', ignoring malformed rule definition", filterAttribute); // NON-NLS + logger.log(Level.SEVERE, "Found {0} " + FilesSetXML.TYPE_FILTER_ATTR + " attribute with unrecognized value ''{0}'', ignoring malformed rule definition", conditionAttribute); // NON-NLS break; } } else { // Accept TSK Framework interesting files set definitions, // default to files. - filter = new FilesSet.Rule.MetaTypeFilter(FilesSet.Rule.MetaTypeFilter.Type.FILES); + condition = new FilesSet.Rule.MetaTypeCondition(FilesSet.Rule.MetaTypeCondition.Type.FILES); } - return filter; + return condition; } /** - * Construct a path filter for an interesting files set membership rule - * from data in an XML element. + * Construct a path condition for an interesting files set membership + * rule from data in an XML element. * * @param ruleElement The XML element. * - * @return The path filter, or null if there is an error (logged). + * @return The path condition, or null if there is an error (logged). */ - private static FilesSet.Rule.ParentPathFilter readPathFilter(Element ruleElement) { - FilesSet.Rule.ParentPathFilter filter = null; + private static FilesSet.Rule.ParentPathCondition readPathCondition(Element ruleElement) { + FilesSet.Rule.ParentPathCondition condition = null; String path = ruleElement.getAttribute(FilesSetXML.PATH_FILTER_ATTR); String pathRegex = ruleElement.getAttribute(FilesSetXML.PATH_REGEX_ATTR); if (!pathRegex.isEmpty() && path.isEmpty()) { try { Pattern pattern = Pattern.compile(pathRegex); - filter = new FilesSet.Rule.ParentPathFilter(pattern); + condition = new FilesSet.Rule.ParentPathCondition(pattern); } catch (PatternSyntaxException ex) { - logger.log(Level.SEVERE, "Error compiling " + FilesSetXML.PATH_REGEX_ATTR + " regex, ignoring malformed path filter definition", ex); // NON-NLS + logger.log(Level.SEVERE, "Error compiling " + FilesSetXML.PATH_REGEX_ATTR + " regex, ignoring malformed path condition definition", ex); // NON-NLS } } else if (!path.isEmpty() && pathRegex.isEmpty()) { - filter = new FilesSet.Rule.ParentPathFilter(path); + condition = new FilesSet.Rule.ParentPathCondition(path); } - return filter; + return condition; } /** @@ -498,85 +515,33 @@ final class InterestingItemDefsManager extends Observable { // Note: This method takes a file path to support the possibility of // multiple intersting files set definition files, e.g., one for // definitions that ship with Autopsy and one for user definitions. - static boolean writeDefinitionsFile(String filePath, Map interestingFilesSets) { - DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); - try { - // Create the new XML document. - DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); - Document doc = docBuilder.newDocument(); - Element rootElement = doc.createElement(FilesSetXML.FILE_SETS_ROOT_TAG); - doc.appendChild(rootElement); - - // Add the interesting files sets to the document. - for (FilesSet set : interestingFilesSets.values()) { - // Add the files set element and its attributes. - Element setElement = doc.createElement(FilesSetXML.FILE_SET_TAG); - setElement.setAttribute(FilesSetXML.NAME_ATTR, set.getName()); - setElement.setAttribute(FilesSetXML.DESC_ATTR, set.getDescription()); - setElement.setAttribute(FilesSetXML.IGNORE_KNOWN_FILES_ATTR, Boolean.toString(set.ignoresKnownFiles())); - - // Add the child elements for the set membership rules. - for (FilesSet.Rule rule : set.getRules().values()) { - // Add a rule element with the appropriate name filter - // type tag. - FilesSet.Rule.FileNameFilter nameFilter = rule.getFileNameFilter(); - Element ruleElement; - if (nameFilter instanceof FilesSet.Rule.FullNameFilter) { - ruleElement = doc.createElement(FilesSetXML.NAME_RULE_TAG); - } else { - ruleElement = doc.createElement(FilesSetXML.EXTENSION_RULE_TAG); - } - - // Add the rule name attribute. - ruleElement.setAttribute(FilesSetXML.NAME_ATTR, rule.getName()); - - // Add the name filter regex attribute - ruleElement.setAttribute(FilesSetXML.REGEX_ATTR, Boolean.toString(nameFilter.isRegex())); - - // Add the type filter attribute. - FilesSet.Rule.MetaTypeFilter typeFilter = rule.getMetaTypeFilter(); - switch (typeFilter.getMetaType()) { - case FILES: - ruleElement.setAttribute(FilesSetXML.TYPE_FILTER_ATTR, FilesSetXML.TYPE_FILTER_VALUE_FILES); - break; - case DIRECTORIES: - ruleElement.setAttribute(FilesSetXML.TYPE_FILTER_ATTR, FilesSetXML.TYPE_FILTER_VALUE_DIRS); - break; - default: - ruleElement.setAttribute(FilesSetXML.TYPE_FILTER_ATTR, FilesSetXML.TYPE_FILTER_VALUE_FILES_AND_DIRS); - break; - } - - // Add the optional path filter. - FilesSet.Rule.ParentPathFilter pathFilter = rule.getPathFilter(); - if (pathFilter != null) { - if (pathFilter.isRegex()) { - ruleElement.setAttribute(FilesSetXML.PATH_REGEX_ATTR, pathFilter.getTextToMatch()); - } else { - ruleElement.setAttribute(FilesSetXML.PATH_FILTER_ATTR, pathFilter.getTextToMatch()); - } - } - - // Add the name filter text as the rule element content. - ruleElement.setTextContent(nameFilter.getTextToMatch()); - - setElement.appendChild(ruleElement); - } - - rootElement.appendChild(setElement); - } - - // Overwrite the previous definitions file. Note that the utility - // method logs an error on failure. - return XMLUtil.saveDoc(FilesSetXML.class, filePath, XML_ENCODING, doc); - - } catch (ParserConfigurationException ex) { - logger.log(Level.SEVERE, "Error writing interesting files definition file to " + filePath, ex); // NON-NLS - return false; + static boolean writeDefinitionsFile(String filePath, Map interestingFilesSets) throws InterestingItemDefsManagerException { + try (NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(filePath))) { + out.writeObject(new InterestingItemsFilesSetSettings(interestingFilesSets)); + } catch (IOException ex) { + throw new InterestingItemDefsManagerException(String.format("Failed to write settings to %s", filePath), ex); } + return true; + } + } + + static class InterestingItemDefsManagerException extends Exception { + + InterestingItemDefsManagerException() { } + InterestingItemDefsManagerException(String message) { + super(message); + } + + InterestingItemDefsManagerException(String message, Throwable cause) { + super(message, cause); + } + + InterestingItemDefsManagerException(Throwable cause) { + super(cause); + } } } diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsPanel.form b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsPanel.form index 6b92c6b39f..e55060f6a1 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsPanel.form @@ -4,6 +4,8 @@ + + @@ -28,18 +30,14 @@ - - - + + - - - - + @@ -67,7 +65,7 @@ - + @@ -83,65 +81,104 @@ - + - - - - - - - - - - - - - - - - + + + + + - - - + + + + + + + + + + + + + + + + + - - - - - - - - - - - + + + + - + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - - + + + + + + + + + + + + + - + @@ -149,65 +186,81 @@ - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + - + - - - - - - - - - + + - - - + + + + + + + + + @@ -242,7 +295,6 @@ - @@ -250,6 +302,9 @@ + + + @@ -442,6 +497,9 @@ + + + @@ -471,16 +529,16 @@ - + - + - + @@ -532,6 +590,9 @@ + + + @@ -613,6 +674,9 @@ + + + @@ -651,15 +715,15 @@ - + - + - + @@ -700,6 +764,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsPanel.java index caa6098f55..61271fc54c 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2014 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,25 +20,51 @@ package org.sleuthkit.autopsy.modules.interestingitems; import java.awt.EventQueue; import java.awt.Font; +import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; +import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.SortedSet; import java.util.TreeMap; +import java.util.logging.Level; import javax.swing.DefaultListModel; +import javax.swing.JButton; import javax.swing.JOptionPane; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; +import org.apache.tika.mime.MediaType; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.corecomponents.OptionsPanel; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSettingsPanel; +import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; +import org.apache.tika.mime.MediaType; +import org.apache.tika.mime.MimeTypes; +import org.openide.util.Exceptions; +import org.sleuthkit.autopsy.coreutils.Logger; /** * A panel that allows a user to make interesting item definitions. */ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel implements OptionsPanel { + @NbBundle.Messages({ + "InterestingItemDefsPanel.bytes=Bytes", + "InterestingItemDefsPanel.kiloBytes=Kilobytes", + "InterestingItemDefsPanel.megaBytes=Megabytes", + "InterestingItemDefsPanel.gigaBytes=Gigabytes", + "InterestingItemsDefsPanel.loadError=Error loading interesting files sets from file.", + "InterestingItemsDefsPanel.saveError=Error saving interesting files sets to file." + }) + + private static final SortedSet mediaTypes = MimeTypes.getDefaultMimeTypes().getMediaTypeRegistry().getTypes(); private final DefaultListModel setsListModel = new DefaultListModel<>(); private final DefaultListModel rulesListModel = new DefaultListModel<>(); + private final Logger logger = Logger.getLogger(InterestingItemDefsPanel.class.getName()); + private JButton okButton = new JButton("OK"); + private JButton cancelButton = new JButton("Cancel"); // The following is a map of interesting files set names to interesting // files set definitions. It is a snapshot of the files set definitions @@ -54,18 +80,58 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp */ InterestingItemDefsPanel() { this.initComponents(); + this.customInit(); this.setsList.setModel(setsListModel); this.setsList.addListSelectionListener(new InterestingItemDefsPanel.SetsListSelectionListener()); this.rulesList.setModel(rulesListModel); this.rulesList.addListSelectionListener(new InterestingItemDefsPanel.RulesListSelectionListener()); } + @NbBundle.Messages({"InterestingItemDefsPanel.Title=Global Interesting Items Settings"}) + private void customInit() { + setName(Bundle.InterestingItemDefsPanel_Title()); + + Set fileTypesCollated = new HashSet<>(); + for (MediaType mediaType : mediaTypes) { + fileTypesCollated.add(mediaType.toString()); + } + + FileTypeDetector fileTypeDetector; + try { + fileTypeDetector = new FileTypeDetector(); + List userDefinedFileTypes = fileTypeDetector.getUserDefinedTypes(); + fileTypesCollated.addAll(userDefinedFileTypes); + + } catch (FileTypeDetector.FileTypeDetectorInitException ex) { + logger.log(Level.SEVERE, "Unable to get user defined file types", ex); + } + + List toSort = new ArrayList<>(fileTypesCollated); + toSort.sort((String string1, String string2) -> { + int result = String.CASE_INSENSITIVE_ORDER.compare(string1, string2); + if (result == 0) { + result = string1.compareTo(string2); + } + return result; + }); + + for (String file : toSort) { + mimeTypeComboBox.addItem(file); + } + this.fileSizeUnitComboBox.setSelectedIndex(1); + this.equalitySignComboBox.setSelectedIndex(2); + } + /** * @inheritDoc */ @Override public void saveSettings() { - InterestingItemDefsManager.getInstance().setInterestingFilesSets(this.filesSets); + try { + InterestingItemDefsManager.getInstance().setInterestingFilesSets(this.filesSets); + } catch (InterestingItemDefsManager.InterestingItemDefsManagerException ex) { + MessageNotifyUtil.Message.error(Bundle.InterestingItemsDefsPanel_saveError()); + } } /** @@ -83,9 +149,14 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp public void load() { this.resetComponents(); - // Get a working copy of the interesting files set definitions and sort - // by set name. - this.filesSets = new TreeMap<>(InterestingItemDefsManager.getInstance().getInterestingFilesSets()); + try { + // Get a working copy of the interesting files set definitions and sort + // by set name. + this.filesSets = new TreeMap<>(InterestingItemDefsManager.getInstance().getInterestingFilesSets()); + } catch (InterestingItemDefsManager.InterestingItemDefsManagerException ex) { + MessageNotifyUtil.Message.error(Bundle.InterestingItemsDefsPanel_loadError()); + this.filesSets = new TreeMap<>(); + } // Populate the list model for the interesting files sets list // component. @@ -124,8 +195,8 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp this.fileNameRadioButton.setSelected(true); this.fileNameRegexCheckbox.setSelected(false); this.filesRadioButton.setSelected(true); - this.rulePathFilterTextField.setText(""); - this.rulePathFilterRegexCheckBox.setSelected(false); + this.rulePathConditionTextField.setText(""); + this.rulePathConditionRegexCheckBox.setSelected(false); this.newRuleButton.setEnabled(!this.setsListModel.isEmpty()); this.editRuleButton.setEnabled(false); this.deleteRuleButton.setEnabled(false); @@ -189,18 +260,27 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp // Get the selected rule and populate the rule components. FilesSet.Rule rule = InterestingItemDefsPanel.this.rulesList.getSelectedValue(); if (rule != null) { - // Get the filters that make up the rule. - FilesSet.Rule.FileNameFilter nameFilter = rule.getFileNameFilter(); - FilesSet.Rule.MetaTypeFilter typeFilter = rule.getMetaTypeFilter(); - FilesSet.Rule.ParentPathFilter pathFilter = rule.getPathFilter(); + // Get the conditions that make up the rule. + FilesSet.Rule.FileNameCondition nameCondition = rule.getFileNameCondition(); + FilesSet.Rule.MetaTypeCondition typeCondition = rule.getMetaTypeCondition(); + FilesSet.Rule.ParentPathCondition pathCondition = rule.getPathCondition(); + FilesSet.Rule.MimeTypeCondition mimeTypeCondition = rule.getMimeTypeCondition(); + FilesSet.Rule.FileSizeCondition fileSizeCondition = rule.getFileSizeCondition(); // Populate the components that display the properties of the // selected rule. - InterestingItemDefsPanel.this.fileNameTextField.setText(nameFilter.getTextToMatch()); - InterestingItemDefsPanel.this.fileNameRadioButton.setSelected(nameFilter instanceof FilesSet.Rule.FullNameFilter); - InterestingItemDefsPanel.this.fileNameExtensionRadioButton.setSelected(nameFilter instanceof FilesSet.Rule.ExtensionFilter); - InterestingItemDefsPanel.this.fileNameRegexCheckbox.setSelected(nameFilter.isRegex()); - switch (typeFilter.getMetaType()) { + if (nameCondition != null) { + InterestingItemDefsPanel.this.fileNameTextField.setText(nameCondition.getTextToMatch()); + InterestingItemDefsPanel.this.fileNameRadioButton.setSelected(nameCondition instanceof FilesSet.Rule.FullNameCondition); + InterestingItemDefsPanel.this.fileNameExtensionRadioButton.setSelected(nameCondition instanceof FilesSet.Rule.ExtensionCondition); + InterestingItemDefsPanel.this.fileNameRegexCheckbox.setSelected(nameCondition.isRegex()); + } else { + InterestingItemDefsPanel.this.fileNameTextField.setText(""); + InterestingItemDefsPanel.this.fileNameRadioButton.setSelected(true); + InterestingItemDefsPanel.this.fileNameExtensionRadioButton.setSelected(false); + InterestingItemDefsPanel.this.fileNameRegexCheckbox.setSelected(false); + } + switch (typeCondition.getMetaType()) { case FILES: InterestingItemDefsPanel.this.filesRadioButton.setSelected(true); break; @@ -211,12 +291,26 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp InterestingItemDefsPanel.this.bothRadioButton.setSelected(true); break; } - if (pathFilter != null) { - InterestingItemDefsPanel.this.rulePathFilterTextField.setText(pathFilter.getTextToMatch()); - InterestingItemDefsPanel.this.rulePathFilterRegexCheckBox.setSelected(pathFilter.isRegex()); + if (pathCondition != null) { + InterestingItemDefsPanel.this.rulePathConditionTextField.setText(pathCondition.getTextToMatch()); + InterestingItemDefsPanel.this.rulePathConditionRegexCheckBox.setSelected(pathCondition.isRegex()); } else { - InterestingItemDefsPanel.this.rulePathFilterTextField.setText(""); - InterestingItemDefsPanel.this.rulePathFilterRegexCheckBox.setSelected(false); + InterestingItemDefsPanel.this.rulePathConditionTextField.setText(""); + InterestingItemDefsPanel.this.rulePathConditionRegexCheckBox.setSelected(false); + } + if (mimeTypeCondition != null) { + InterestingItemDefsPanel.this.mimeTypeComboBox.setSelectedItem(mimeTypeCondition.getMimeType()); + } else { + InterestingItemDefsPanel.this.mimeTypeComboBox.setSelectedIndex(0); + } + if (fileSizeCondition != null) { + InterestingItemDefsPanel.this.fileSizeUnitComboBox.setSelectedItem(fileSizeCondition.getUnit().getName()); + InterestingItemDefsPanel.this.equalitySignComboBox.setSelectedItem(fileSizeCondition.getComparator().getSymbol()); + InterestingItemDefsPanel.this.jSpinner1.setValue(fileSizeCondition.getSizeValue()); + } else { + InterestingItemDefsPanel.this.fileSizeUnitComboBox.setSelectedIndex(1); + InterestingItemDefsPanel.this.equalitySignComboBox.setSelectedIndex(2); + InterestingItemDefsPanel.this.jSpinner1.setValue(0); } // Enable the new, edit and delete rule buttons. @@ -290,18 +384,17 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp FilesSetRulePanel panel; if (selectedRule != null) { // Editing an existing rule definition. - panel = new FilesSetRulePanel(selectedRule); + panel = new FilesSetRulePanel(selectedRule, okButton, cancelButton); } else { // Creating a new rule definition. - panel = new FilesSetRulePanel(); + panel = new FilesSetRulePanel(okButton, cancelButton); } - // Do a dialog box with the files set panel until the user either enters // a valid definition or cancels. Note that the panel gives the user // feedback when isValidDefinition() is called. int option = JOptionPane.OK_OPTION; do { - option = JOptionPane.showConfirmDialog(null, panel, NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.title"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE); + option = JOptionPane.showOptionDialog(null, panel, NbBundle.getMessage(FilesSetPanel.class, "FilesSetPanel.title"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, new Object[]{okButton, cancelButton}, okButton); } while (option == JOptionPane.OK_OPTION && !panel.isValidRuleDefinition()); if (option == JOptionPane.OK_OPTION) { @@ -316,7 +409,7 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp if (selectedRule != null) { rules.remove(selectedRule.getUuid()); } - FilesSet.Rule newRule = new FilesSet.Rule(panel.getRuleName(), panel.getFileNameFilter(), panel.getMetaTypeFilter(), panel.getPathFilter()); + FilesSet.Rule newRule = new FilesSet.Rule(panel.getRuleName(), panel.getFileNameCondition(), panel.getMetaTypeCondition(), panel.getPathCondition(), panel.getMimeTypeCondition(), panel.getFileSizeCondition()); rules.put(newRule.getUuid(), newRule); // Add the new/edited files set definition, replacing any previous @@ -380,6 +473,7 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp private void initComponents() { fileNameButtonGroup = new javax.swing.ButtonGroup(); + typeButtonGroup = new javax.swing.ButtonGroup(); jScrollPane1 = new javax.swing.JScrollPane(); jPanel1 = new javax.swing.JPanel(); jLabel6 = new javax.swing.JLabel(); @@ -388,18 +482,18 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp editRuleButton = new javax.swing.JButton(); rulesListLabel = new javax.swing.JLabel(); rulesListScrollPane = new javax.swing.JScrollPane(); - rulesList = new javax.swing.JList<>(); + rulesList = new javax.swing.JList(); setDescScrollPanel = new javax.swing.JScrollPane(); setDescriptionTextArea = new javax.swing.JTextArea(); editSetButton = new javax.swing.JButton(); setsListScrollPane = new javax.swing.JScrollPane(); - setsList = new javax.swing.JList<>(); + setsList = new javax.swing.JList(); fileNameExtensionRadioButton = new javax.swing.JRadioButton(); jLabel3 = new javax.swing.JLabel(); fileNameTextField = new javax.swing.JTextField(); jLabel5 = new javax.swing.JLabel(); fileNameRadioButton = new javax.swing.JRadioButton(); - rulePathFilterTextField = new javax.swing.JTextField(); + rulePathConditionTextField = new javax.swing.JTextField(); ignoreKnownFilesCheckbox = new javax.swing.JCheckBox(); fileNameRegexCheckbox = new javax.swing.JCheckBox(); separator = new javax.swing.JSeparator(); @@ -412,9 +506,15 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp dirsRadioButton = new javax.swing.JRadioButton(); jLabel1 = new javax.swing.JLabel(); jLabel4 = new javax.swing.JLabel(); - rulePathFilterRegexCheckBox = new javax.swing.JCheckBox(); + rulePathConditionRegexCheckBox = new javax.swing.JCheckBox(); jScrollPane2 = new javax.swing.JScrollPane(); jTextArea1 = new javax.swing.JTextArea(); + jLabel7 = new javax.swing.JLabel(); + mimeTypeComboBox = new javax.swing.JComboBox(); + jLabel8 = new javax.swing.JLabel(); + equalitySignComboBox = new javax.swing.JComboBox(); + jSpinner1 = new javax.swing.JSpinner(); + fileSizeUnitComboBox = new javax.swing.JComboBox(); setFont(getFont().deriveFont(getFont().getStyle() & ~java.awt.Font.BOLD, 11)); @@ -428,13 +528,13 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp newRuleButton.setFont(newRuleButton.getFont().deriveFont(newRuleButton.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); newRuleButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/add16.png"))); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(newRuleButton, org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.newRuleButton.text")); // NOI18N - newRuleButton.setEnabled(false); newRuleButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { newRuleButtonActionPerformed(evt); } }); + typeButtonGroup.add(filesRadioButton); filesRadioButton.setFont(filesRadioButton.getFont().deriveFont(filesRadioButton.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); filesRadioButton.setSelected(true); org.openide.awt.Mnemonics.setLocalizedText(filesRadioButton, org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.filesRadioButton.text")); // NOI18N @@ -496,6 +596,11 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp fileNameTextField.setEditable(false); fileNameTextField.setFont(fileNameTextField.getFont().deriveFont(fileNameTextField.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); fileNameTextField.setText(org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.fileNameTextField.text")); // NOI18N + fileNameTextField.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + fileNameTextFieldActionPerformed(evt); + } + }); jLabel5.setFont(jLabel5.getFont().deriveFont(jLabel5.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); org.openide.awt.Mnemonics.setLocalizedText(jLabel5, org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.jLabel5.text")); // NOI18N @@ -505,9 +610,9 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp org.openide.awt.Mnemonics.setLocalizedText(fileNameRadioButton, org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.fileNameRadioButton.text")); // NOI18N fileNameRadioButton.setEnabled(false); - rulePathFilterTextField.setEditable(false); - rulePathFilterTextField.setFont(rulePathFilterTextField.getFont().deriveFont(rulePathFilterTextField.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); - rulePathFilterTextField.setText(org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.rulePathFilterTextField.text")); // NOI18N + rulePathConditionTextField.setEditable(false); + rulePathConditionTextField.setFont(rulePathConditionTextField.getFont().deriveFont(rulePathConditionTextField.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); + rulePathConditionTextField.setText(org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.rulePathConditionTextField.text")); // NOI18N ignoreKnownFilesCheckbox.setFont(ignoreKnownFilesCheckbox.getFont().deriveFont(ignoreKnownFilesCheckbox.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); org.openide.awt.Mnemonics.setLocalizedText(ignoreKnownFilesCheckbox, org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.ignoreKnownFilesCheckbox.text")); // NOI18N @@ -527,6 +632,7 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp setsListLabel.setFont(setsListLabel.getFont().deriveFont(setsListLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); org.openide.awt.Mnemonics.setLocalizedText(setsListLabel, org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.setsListLabel.text")); // NOI18N + typeButtonGroup.add(bothRadioButton); bothRadioButton.setFont(bothRadioButton.getFont().deriveFont(bothRadioButton.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); org.openide.awt.Mnemonics.setLocalizedText(bothRadioButton, org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.bothRadioButton.text")); // NOI18N bothRadioButton.setEnabled(false); @@ -563,6 +669,7 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp jLabel2.setFont(jLabel2.getFont().deriveFont(jLabel2.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.jLabel2.text")); // NOI18N + typeButtonGroup.add(dirsRadioButton); dirsRadioButton.setFont(dirsRadioButton.getFont().deriveFont(dirsRadioButton.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); org.openide.awt.Mnemonics.setLocalizedText(dirsRadioButton, org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.dirsRadioButton.text")); // NOI18N dirsRadioButton.setEnabled(false); @@ -578,9 +685,9 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp jLabel4.setFont(jLabel4.getFont().deriveFont(jLabel4.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); org.openide.awt.Mnemonics.setLocalizedText(jLabel4, org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.jLabel4.text")); // NOI18N - rulePathFilterRegexCheckBox.setFont(rulePathFilterRegexCheckBox.getFont().deriveFont(rulePathFilterRegexCheckBox.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); - org.openide.awt.Mnemonics.setLocalizedText(rulePathFilterRegexCheckBox, org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.rulePathFilterRegexCheckBox.text")); // NOI18N - rulePathFilterRegexCheckBox.setEnabled(false); + rulePathConditionRegexCheckBox.setFont(rulePathConditionRegexCheckBox.getFont().deriveFont(rulePathConditionRegexCheckBox.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); + org.openide.awt.Mnemonics.setLocalizedText(rulePathConditionRegexCheckBox, org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.rulePathConditionRegexCheckBox.text")); // NOI18N + rulePathConditionRegexCheckBox.setEnabled(false); jScrollPane2.setFont(jScrollPane2.getFont().deriveFont(jScrollPane2.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); @@ -594,6 +701,22 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp jTextArea1.setWrapStyleWord(true); jScrollPane2.setViewportView(jTextArea1); + org.openide.awt.Mnemonics.setLocalizedText(jLabel7, org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.jLabel7.text")); // NOI18N + + mimeTypeComboBox.setEditable(true); + mimeTypeComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] {""})); + mimeTypeComboBox.setEnabled(false); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel8, org.openide.util.NbBundle.getMessage(InterestingItemDefsPanel.class, "InterestingItemDefsPanel.jLabel8.text")); // NOI18N + + equalitySignComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "=", ">", "≥", "<", "≤" })); + equalitySignComboBox.setEnabled(false); + + jSpinner1.setEnabled(false); + + fileSizeUnitComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { Bundle.InterestingItemDefsPanel_bytes(), Bundle.InterestingItemDefsPanel_kiloBytes(), Bundle.InterestingItemDefsPanel_megaBytes(), Bundle.InterestingItemDefsPanel_gigaBytes() })); + fileSizeUnitComboBox.setEnabled(false); + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); jPanel1.setLayout(jPanel1Layout); jPanel1Layout.setHorizontalGroup( @@ -611,112 +734,152 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp .addComponent(editSetButton, javax.swing.GroupLayout.PREFERRED_SIZE, 89, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(deleteSetButton))) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGap(18, 18, 18) .addComponent(separator, javax.swing.GroupLayout.PREFERRED_SIZE, 6, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(10, 10, 10) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(rulesListLabel) - .addComponent(jLabel5) - .addComponent(ignoreKnownFilesCheckbox) + .addGap(12, 12, 12) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addGroup(jPanel1Layout.createSequentialGroup() - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(jLabel2) - .addComponent(jLabel1)) - .addGap(18, 18, 18) - .addComponent(filesRadioButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(jLabel1) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(jLabel2) + .addGap(27, 27, 27) + .addComponent(filesRadioButton, javax.swing.GroupLayout.PREFERRED_SIZE, 47, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(dirsRadioButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(bothRadioButton)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(bothRadioButton) + .addGap(27, 27, 27)))) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createSequentialGroup() - .addGap(9, 9, 9) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addGap(380, 380, 380) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createSequentialGroup() - .addGap(2, 2, 2) - .addComponent(jLabel3) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel1Layout.createSequentialGroup() - .addComponent(fileNameRadioButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(fileNameExtensionRadioButton, javax.swing.GroupLayout.PREFERRED_SIZE, 114, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(fileNameRegexCheckbox)) - .addComponent(fileNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 250, javax.swing.GroupLayout.PREFERRED_SIZE))) - .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(jLabel3) + .addComponent(jLabel7) + .addComponent(jLabel8)) + .addGap(6, 6, 6)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() .addComponent(jLabel4) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(rulePathFilterRegexCheckBox) - .addComponent(rulePathFilterTextField))))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED))) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) + .addComponent(rulePathConditionTextField, javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel1Layout.createSequentialGroup() + .addComponent(equalitySignComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 38, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jSpinner1, javax.swing.GroupLayout.PREFERRED_SIZE, 104, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(fileSizeUnitComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 83, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(mimeTypeComboBox, javax.swing.GroupLayout.Alignment.LEADING, 0, 245, Short.MAX_VALUE) + .addComponent(fileNameTextField))) .addGroup(jPanel1Layout.createSequentialGroup() + .addGap(360, 360, 360) + .addComponent(rulesListLabel)) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGap(360, 360, 360) + .addComponent(jLabel5)) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGap(360, 360, 360) + .addComponent(ignoreKnownFilesCheckbox)) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGap(360, 360, 360) + .addComponent(setDescScrollPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 336, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGap(360, 360, 360) + .addComponent(jLabel6)) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGap(360, 360, 360) + .addComponent(rulesListScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 336, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGap(360, 360, 360) .addComponent(newRuleButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGap(18, 18, 18) .addComponent(editRuleButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGap(18, 18, 18) .addComponent(deleteRuleButton)) - .addComponent(setDescScrollPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 336, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(jLabel6) - .addComponent(rulesListScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 336, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addContainerGap()) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGap(456, 456, 456) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(fileNameRadioButton) + .addGap(4, 4, 4) + .addComponent(fileNameExtensionRadioButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(fileNameRegexCheckbox)) + .addComponent(rulePathConditionRegexCheckBox)))) + .addGap(20, 20, 20)) ); jPanel1Layout.setVerticalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createSequentialGroup() .addContainerGap() - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) - .addComponent(separator, javax.swing.GroupLayout.PREFERRED_SIZE, 444, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(separator) .addGroup(jPanel1Layout.createSequentialGroup() - .addComponent(jLabel6) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(jLabel5) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(setDescScrollPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 53, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(ignoreKnownFilesCheckbox) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(rulesListLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(rulesListScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 110, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(newRuleButton) - .addComponent(editRuleButton) - .addComponent(deleteRuleButton)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(jLabel1) - .addGap(2, 2, 2) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(jLabel2) - .addComponent(filesRadioButton) - .addComponent(dirsRadioButton) - .addComponent(bothRadioButton)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(jLabel3) - .addComponent(fileNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(fileNameRadioButton) - .addComponent(fileNameExtensionRadioButton) - .addComponent(fileNameRegexCheckbox)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(18, 18, 18) + .addComponent(setsListLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(setsListScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 199, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(newSetButton) + .addComponent(editSetButton) + .addComponent(deleteSetButton))) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(jLabel6) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel5) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(setDescScrollPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 42, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(ignoreKnownFilesCheckbox) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(rulesListLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(rulesListScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 64, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(newRuleButton) + .addComponent(editRuleButton) + .addComponent(deleteRuleButton)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel1) + .addGap(2, 2, 2) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel2) + .addComponent(filesRadioButton) + .addComponent(dirsRadioButton) + .addComponent(bothRadioButton)) + .addGap(16, 16, 16) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel3) + .addComponent(fileNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(fileNameRadioButton) + .addComponent(fileNameExtensionRadioButton) + .addComponent(fileNameRegexCheckbox)))) + .addGap(14, 14, 14) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel4) - .addComponent(rulePathFilterTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(rulePathFilterRegexCheckBox)) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel1Layout.createSequentialGroup() - .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(18, 18, 18) - .addComponent(setsListLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(setsListScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 199, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(rulePathConditionTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(rulePathConditionRegexCheckBox) + .addGap(10, 10, 10) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(newSetButton) - .addComponent(editSetButton) - .addComponent(deleteSetButton)))) + .addComponent(jLabel7) + .addComponent(mimeTypeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(16, 16, 16) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel8) + .addComponent(equalitySignComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jSpinner1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(fileSizeUnitComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))) .addContainerGap()) ); @@ -729,33 +892,34 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 710, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 728, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 34, Short.MAX_VALUE)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addGap(0, 11, Short.MAX_VALUE) - .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 468, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 503, Short.MAX_VALUE) ); }// //GEN-END:initComponents + private void dirsRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dirsRadioButtonActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_dirsRadioButtonActionPerformed + private void newSetButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newSetButtonActionPerformed this.doFileSetsDialog(null); }//GEN-LAST:event_newSetButtonActionPerformed - private void editSetButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editSetButtonActionPerformed - this.doFileSetsDialog(this.setsList.getSelectedValue()); - }//GEN-LAST:event_editSetButtonActionPerformed - - private void newRuleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newRuleButtonActionPerformed - this.doFilesSetRuleDialog(null); - }//GEN-LAST:event_newRuleButtonActionPerformed - - private void editRuleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editRuleButtonActionPerformed - this.doFilesSetRuleDialog(this.rulesList.getSelectedValue()); - }//GEN-LAST:event_editRuleButtonActionPerformed + private void deleteRuleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteRuleButtonActionPerformed + // Interesting file sets are immutable for thread safety, + // so editing a files set rule definition is a replacement + // operation. Preserve the existing rules from the set being + // edited, except for the deleted rule. + FilesSet oldSet = this.setsList.getSelectedValue(); + Map rules = new HashMap<>(oldSet.getRules()); + FilesSet.Rule selectedRule = this.rulesList.getSelectedValue(); + rules.remove(selectedRule.getUuid()); + this.replaceFilesSet(oldSet, oldSet.getName(), oldSet.getDescription(), oldSet.ignoresKnownFiles(), rules); + }//GEN-LAST:event_deleteRuleButtonActionPerformed private void deleteSetButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteSetButtonActionPerformed FilesSet selectedSet = this.setsList.getSelectedValue(); @@ -771,25 +935,25 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp } }//GEN-LAST:event_deleteSetButtonActionPerformed - private void deleteRuleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteRuleButtonActionPerformed - // Interesting file sets are immutable for thread safety, - // so editing a files set rule definition is a replacement - // operation. Preserve the existing rules from the set being - // edited, except for the deleted rule. - FilesSet oldSet = this.setsList.getSelectedValue(); - Map rules = new HashMap<>(oldSet.getRules()); - FilesSet.Rule selectedRule = this.rulesList.getSelectedValue(); - rules.remove(selectedRule.getUuid()); - this.replaceFilesSet(oldSet, oldSet.getName(), oldSet.getDescription(), oldSet.ignoresKnownFiles(), rules); - }//GEN-LAST:event_deleteRuleButtonActionPerformed - private void ignoreKnownFilesCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ignoreKnownFilesCheckboxActionPerformed // TODO add your handling code here: }//GEN-LAST:event_ignoreKnownFilesCheckboxActionPerformed - private void dirsRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dirsRadioButtonActionPerformed + private void editSetButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editSetButtonActionPerformed + this.doFileSetsDialog(this.setsList.getSelectedValue()); + }//GEN-LAST:event_editSetButtonActionPerformed + + private void editRuleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editRuleButtonActionPerformed + this.doFilesSetRuleDialog(this.rulesList.getSelectedValue()); + }//GEN-LAST:event_editRuleButtonActionPerformed + + private void newRuleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newRuleButtonActionPerformed + this.doFilesSetRuleDialog(null); + }//GEN-LAST:event_newRuleButtonActionPerformed + + private void fileNameTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fileNameTextFieldActionPerformed // TODO add your handling code here: - }//GEN-LAST:event_dirsRadioButtonActionPerformed + }//GEN-LAST:event_fileNameTextFieldActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JRadioButton bothRadioButton; @@ -798,11 +962,13 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp private javax.swing.JRadioButton dirsRadioButton; private javax.swing.JButton editRuleButton; private javax.swing.JButton editSetButton; + private javax.swing.JComboBox equalitySignComboBox; private javax.swing.ButtonGroup fileNameButtonGroup; private javax.swing.JRadioButton fileNameExtensionRadioButton; private javax.swing.JRadioButton fileNameRadioButton; private javax.swing.JCheckBox fileNameRegexCheckbox; private javax.swing.JTextField fileNameTextField; + private javax.swing.JComboBox fileSizeUnitComboBox; private javax.swing.JRadioButton filesRadioButton; private javax.swing.JCheckBox ignoreKnownFilesCheckbox; private javax.swing.JLabel jLabel1; @@ -811,14 +977,18 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp private javax.swing.JLabel jLabel4; private javax.swing.JLabel jLabel5; private javax.swing.JLabel jLabel6; + private javax.swing.JLabel jLabel7; + private javax.swing.JLabel jLabel8; private javax.swing.JPanel jPanel1; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JScrollPane jScrollPane2; + private javax.swing.JSpinner jSpinner1; private javax.swing.JTextArea jTextArea1; + private javax.swing.JComboBox mimeTypeComboBox; private javax.swing.JButton newRuleButton; private javax.swing.JButton newSetButton; - private javax.swing.JCheckBox rulePathFilterRegexCheckBox; - private javax.swing.JTextField rulePathFilterTextField; + private javax.swing.JCheckBox rulePathConditionRegexCheckBox; + private javax.swing.JTextField rulePathConditionTextField; private javax.swing.JList rulesList; private javax.swing.JLabel rulesListLabel; private javax.swing.JScrollPane rulesListScrollPane; @@ -828,6 +998,7 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp private javax.swing.JList setsList; private javax.swing.JLabel setsListLabel; private javax.swing.JScrollPane setsListScrollPane; + private javax.swing.ButtonGroup typeButtonGroup; // End of variables declaration//GEN-END:variables } diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemsFilesSetSettings.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemsFilesSetSettings.java new file mode 100755 index 0000000000..14771992eb --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemsFilesSetSettings.java @@ -0,0 +1,44 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-2016 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.modules.interestingitems; + +import java.io.Serializable; +import java.util.Map; + +/** + * + * @author oliver + */ +class InterestingItemsFilesSetSettings implements Serializable { + private static final long serialVersionUID = 1L; + private Map filesSets; + InterestingItemsFilesSetSettings(Map filesSets) { + this.filesSets = filesSets; + } + + /** + * @return the filesSets + */ + Map getFilesSets() { + return filesSets; + } + + + +} diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemsIngestModuleFactory.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemsIngestModuleFactory.java index 549e75c963..1779c8b3c2 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemsIngestModuleFactory.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemsIngestModuleFactory.java @@ -20,8 +20,11 @@ package org.sleuthkit.autopsy.modules.interestingitems; import java.util.ArrayList; import java.util.List; +import org.openide.util.Exceptions; import org.openide.util.NbBundle; +import org.openide.util.NbBundle.Messages; import org.openide.util.lookup.ServiceProvider; +import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.Version; import org.sleuthkit.autopsy.ingest.FileIngestModule; import org.sleuthkit.autopsy.ingest.IngestModuleFactory; @@ -37,6 +40,10 @@ import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel; @ServiceProvider(service = IngestModuleFactory.class) final public class InterestingItemsIngestModuleFactory extends IngestModuleFactoryAdapter { + @Messages({ + "InterestingItemsIngestModuleFactory.defaultSettingsError=Error getting default interesting files settings from file." + }) + @Override public String getModuleDisplayName() { return getModuleName(); @@ -76,8 +83,12 @@ final public class InterestingItemsIngestModuleFactory extends IngestModuleFacto // definitions independent of the rules that make up the defintions. // Doing so also keeps the serialization simple. List enabledFilesSetNames = new ArrayList<>(); - for (String name : InterestingItemDefsManager.getInstance().getInterestingFilesSets().keySet()) { - enabledFilesSetNames.add(name); + try { + for (String name : InterestingItemDefsManager.getInstance().getInterestingFilesSets().keySet()) { + enabledFilesSetNames.add(name); + } + } catch (InterestingItemDefsManager.InterestingItemDefsManagerException ex) { + MessageNotifyUtil.Message.error(Bundle.InterestingItemsIngestModuleFactory_defaultSettingsError()); } return new FilesIdentifierIngestJobSettings(enabledFilesSetNames); } diff --git a/Core/src/org/sleuthkit/autopsy/modules/photoreccarver/PhotoRecCarverFileIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/photoreccarver/PhotoRecCarverFileIngestModule.java index f848838d02..16ae16e4bd 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/photoreccarver/PhotoRecCarverFileIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/photoreccarver/PhotoRecCarverFileIngestModule.java @@ -152,7 +152,7 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule { // Initialize job totals initTotalsForIngestJob(jobId); } catch (SecurityException | IOException | UnsupportedOperationException ex) { - throw new IngestModule.IngestModuleException(NbBundle.getMessage(PhotoRecCarverFileIngestModule.class, "cannotCreateOutputDir.message", ex.getLocalizedMessage())); + throw new IngestModule.IngestModuleException(NbBundle.getMessage(PhotoRecCarverFileIngestModule.class, "cannotCreateOutputDir.message", ex.getLocalizedMessage()), ex); } } } @@ -396,7 +396,7 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule { } catch (FileAlreadyExistsException ex) { // No worries. } catch (IOException | SecurityException | UnsupportedOperationException ex) { - throw new IngestModule.IngestModuleException(NbBundle.getMessage(PhotoRecCarverFileIngestModule.class, "cannotCreateOutputDir.message", ex.getLocalizedMessage())); + throw new IngestModule.IngestModuleException(NbBundle.getMessage(PhotoRecCarverFileIngestModule.class, "cannotCreateOutputDir.message", ex.getLocalizedMessage()), ex); } return path; } diff --git a/Core/src/org/sleuthkit/autopsy/modules/stix/EvalAccountObj.java b/Core/src/org/sleuthkit/autopsy/modules/stix/EvalAccountObj.java index eaec84d5d1..d2a6b19551 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/stix/EvalAccountObj.java +++ b/Core/src/org/sleuthkit/autopsy/modules/stix/EvalAccountObj.java @@ -115,15 +115,15 @@ class EvalAccountObj extends EvaluatableObject { boolean foundSIDMatch = false; for (BlackboardAttribute attr : art.getAttributes()) { - if ((attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID()) + if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID()) && (haveHomeDir)) { foundHomeDirMatch = compareStringObject(userAccountObj.getHomeDirectory(), attr.getValueString()); } - if ((attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_NAME.getTypeID()) + if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_NAME.getTypeID()) && (haveUsername)) { foundUsernameMatch = compareStringObject(userAccountObj.getUsername(), attr.getValueString()); } - if ((attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_ID.getTypeID()) + if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_ID.getTypeID()) && (haveSID) && (winUserObj != null)) { foundSIDMatch = compareStringObject(winUserObj.getSecurityID(), attr.getValueString()); } diff --git a/Core/src/org/sleuthkit/autopsy/modules/stix/EvalAddressObj.java b/Core/src/org/sleuthkit/autopsy/modules/stix/EvalAddressObj.java index 2df8ffe93e..faaac1dc4e 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/stix/EvalAddressObj.java +++ b/Core/src/org/sleuthkit/autopsy/modules/stix/EvalAddressObj.java @@ -117,7 +117,7 @@ class EvalAddressObj extends EvaluatableObject { for (BlackboardArtifact art : artList) { for (BlackboardAttribute attr : art.getAttributes()) { - if (attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()) { + if (attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()) { if (compareStringObject(addressStr, obj.getAddressValue().getCondition(), obj.getAddressValue().getApplyCondition(), attr.getValueString())) { finalHits.add(art); diff --git a/Core/src/org/sleuthkit/autopsy/modules/stix/EvalDomainObj.java b/Core/src/org/sleuthkit/autopsy/modules/stix/EvalDomainObj.java index 03a8041c1f..2dd6c7f680 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/stix/EvalDomainObj.java +++ b/Core/src/org/sleuthkit/autopsy/modules/stix/EvalDomainObj.java @@ -80,7 +80,7 @@ class EvalDomainObj extends EvaluatableObject { for (BlackboardArtifact art : artList) { for (BlackboardAttribute attr : art.getAttributes()) { - if (attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()) { + if (attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()) { String url = attr.getValueString(); // Check whether the domain name is a substring of the URL (regardless diff --git a/Core/src/org/sleuthkit/autopsy/modules/stix/EvalNetworkShareObj.java b/Core/src/org/sleuthkit/autopsy/modules/stix/EvalNetworkShareObj.java index 98c0d9d95a..843f19c293 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/stix/EvalNetworkShareObj.java +++ b/Core/src/org/sleuthkit/autopsy/modules/stix/EvalNetworkShareObj.java @@ -98,11 +98,11 @@ class EvalNetworkShareObj extends EvaluatableObject { boolean foundLocalPathMatch = false; for (BlackboardAttribute attr : art.getAttributes()) { - if ((attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_REMOTE_PATH.getTypeID()) + if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_REMOTE_PATH.getTypeID()) && (obj.getNetname() != null)) { foundRemotePathMatch = compareStringObject(obj.getNetname(), attr.getValueString()); } - if ((attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCAL_PATH.getTypeID()) + if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCAL_PATH.getTypeID()) && (obj.getLocalPath() != null)) { foundLocalPathMatch = compareStringObject(obj.getLocalPath(), attr.getValueString()); } diff --git a/Core/src/org/sleuthkit/autopsy/modules/stix/EvalURIObj.java b/Core/src/org/sleuthkit/autopsy/modules/stix/EvalURIObj.java index d7ce6b8c7e..c5e598b034 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/stix/EvalURIObj.java +++ b/Core/src/org/sleuthkit/autopsy/modules/stix/EvalURIObj.java @@ -108,7 +108,7 @@ class EvalURIObj extends EvaluatableObject { for (BlackboardArtifact art : artList) { for (BlackboardAttribute attr : art.getAttributes()) { - if (attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()) { + if (attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()) { String modifiedAttrString = attr.getValueString(); if (modifiedAttrString != null) { diff --git a/Core/src/org/sleuthkit/autopsy/modules/stix/EvalURLHistoryObj.java b/Core/src/org/sleuthkit/autopsy/modules/stix/EvalURLHistoryObj.java index 416784dd81..f6a6b67075 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/stix/EvalURLHistoryObj.java +++ b/Core/src/org/sleuthkit/autopsy/modules/stix/EvalURLHistoryObj.java @@ -152,7 +152,7 @@ class EvalURLHistoryObj extends EvaluatableObject { boolean foundBrowserNameMatch = false; for (BlackboardAttribute attr : art.getAttributes()) { - if ((attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL.getTypeID()) + if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL.getTypeID()) && (haveURL)) { if (entry.getURL().getValue() instanceof AnyURIObjectPropertyType) { foundURLMatch = compareStringObject(entry.getURL().getValue().getValue().toString(), @@ -163,12 +163,12 @@ class EvalURLHistoryObj extends EvaluatableObject { addWarning("Non-AnyURIObjectPropertyType found in URL value field"); //NON-NLS } } - if ((attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID()) + if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID()) && (haveHostname)) { foundHostnameMatch = compareStringObject(entry.getHostname().getHostnameValue(), attr.getValueString()); } - if ((attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_REFERRER.getTypeID()) + if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_REFERRER.getTypeID()) && (haveReferrer)) { if (entry.getReferrerURL().getValue() instanceof AnyURIObjectPropertyType) { foundReferrerMatch = compareStringObject(entry.getReferrerURL().getValue().getValue().toString(), @@ -179,17 +179,17 @@ class EvalURLHistoryObj extends EvaluatableObject { addWarning("Non-AnyURIObjectPropertyType found in URL value field"); //NON-NLS } } - if ((attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE.getTypeID()) + if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE.getTypeID()) && (havePageTitle)) { foundPageTitleMatch = compareStringObject(entry.getPageTitle(), attr.getValueString()); } - if ((attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_NAME.getTypeID()) + if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_NAME.getTypeID()) && (haveUserProfile)) { foundUserProfileMatch = compareStringObject(entry.getUserProfileName(), attr.getValueString()); } - if ((attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID()) + if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID()) && (haveBrowserName)) { foundBrowserNameMatch = compareStringObject(obj.getBrowserInformation().getName(), null, null, attr.getValueString()); @@ -240,7 +240,7 @@ class EvalURLHistoryObj extends EvaluatableObject { boolean foundBrowserNameMatch = false; for (BlackboardAttribute attr : art.getAttributes()) { - if ((attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID()) + if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID()) && (haveBrowserName)) { foundBrowserNameMatch = compareStringObject(obj.getBrowserInformation().getName(), null, null, attr.getValueString()); diff --git a/Core/src/org/sleuthkit/autopsy/report/ArtifactSelectionDialog.form b/Core/src/org/sleuthkit/autopsy/report/ArtifactSelectionDialog.form index c4bd675f90..76a6f6cec7 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ArtifactSelectionDialog.form +++ b/Core/src/org/sleuthkit/autopsy/report/ArtifactSelectionDialog.form @@ -87,7 +87,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/report/ArtifactSelectionDialog.java b/Core/src/org/sleuthkit/autopsy/report/ArtifactSelectionDialog.java index a75ab43848..bfdc9deca9 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ArtifactSelectionDialog.java +++ b/Core/src/org/sleuthkit/autopsy/report/ArtifactSelectionDialog.java @@ -27,6 +27,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.EnumMap; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Level; @@ -40,15 +41,14 @@ import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.BlackboardArtifact; -import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.TskCoreException; public class ArtifactSelectionDialog extends javax.swing.JDialog { private ArtifactModel model; private ArtifactRenderer renderer; - private Map artifactStates; - private List artifacts; + private Map artifactTypeSelections; + private List artifactTypes; /** * Creates new form ArtifactSelectionDialog @@ -61,27 +61,31 @@ public class ArtifactSelectionDialog extends javax.swing.JDialog { } /** - * Populate the list of artifacts with all important artifacts. + * Populate the list of artifact types with all important artifact types. */ @SuppressWarnings("deprecation") private void populateList() { try { - ArrayList doNotReport = new ArrayList<>(); - doNotReport.add(BlackboardArtifact.ARTIFACT_TYPE.TSK_GEN_INFO); - doNotReport.add(BlackboardArtifact.ARTIFACT_TYPE.TSK_TOOL_OUTPUT); // output is too unstructured for table review. + ArrayList doNotReport = new ArrayList<>(); + doNotReport.add(new BlackboardArtifact.Type(BlackboardArtifact.ARTIFACT_TYPE.TSK_GEN_INFO.getTypeID(), + BlackboardArtifact.ARTIFACT_TYPE.TSK_GEN_INFO.getLabel(), + BlackboardArtifact.ARTIFACT_TYPE.TSK_GEN_INFO.getDisplayName())); + doNotReport.add(new BlackboardArtifact.Type(BlackboardArtifact.ARTIFACT_TYPE.TSK_TOOL_OUTPUT.getTypeID(), + BlackboardArtifact.ARTIFACT_TYPE.TSK_TOOL_OUTPUT.getLabel(), + BlackboardArtifact.ARTIFACT_TYPE.TSK_TOOL_OUTPUT.getDisplayName())); // output is too unstructured for table review - artifacts = Case.getCurrentCase().getSleuthkitCase().getBlackboardArtifactTypesInUse(); - artifacts.removeAll(doNotReport); - Collections.sort(artifacts, new Comparator() { + artifactTypes = Case.getCurrentCase().getSleuthkitCase().getArtifactTypesInUse(); + artifactTypes.removeAll(doNotReport); + Collections.sort(artifactTypes, new Comparator() { @Override - public int compare(ARTIFACT_TYPE o1, ARTIFACT_TYPE o2) { + public int compare(BlackboardArtifact.Type o1, BlackboardArtifact.Type o2) { return o1.getDisplayName().compareTo(o2.getDisplayName()); } }); - artifactStates = new EnumMap<>(BlackboardArtifact.ARTIFACT_TYPE.class); - for (BlackboardArtifact.ARTIFACT_TYPE type : artifacts) { - artifactStates.put(type, Boolean.TRUE); + artifactTypeSelections = new HashMap<>(); + for (BlackboardArtifact.Type type : artifactTypes) { + artifactTypeSelections.put(type, Boolean.TRUE); } } catch (TskCoreException ex) { Logger.getLogger(ArtifactSelectionDialog.class.getName()).log(Level.SEVERE, "Error getting list of artifacts in use: " + ex.getLocalizedMessage()); //NON-NLS @@ -99,17 +103,19 @@ public class ArtifactSelectionDialog extends javax.swing.JDialog { @Override public void mousePressed(MouseEvent evt) { int index = artifactList.locationToIndex(evt.getPoint()); - BlackboardArtifact.ARTIFACT_TYPE type = model.getElementAt(index); - artifactStates.put(type, !artifactStates.get(type)); + BlackboardArtifact.Type type = model.getElementAt(index); + artifactTypeSelections.put(type, !artifactTypeSelections.get(type)); artifactList.repaint(); } }); } /** - * Display this dialog, and return the selected artifacts. + * Display this dialog, and return the selected artifactTypes. + * + * @return The state of artifact types displayed */ - Map display() { + Map display() { this.setTitle(NbBundle.getMessage(this.getClass(), "ArtifactSelectionDialog.dlgTitle.text")); Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize(); // set the popUp window / JFrame @@ -120,7 +126,7 @@ public class ArtifactSelectionDialog extends javax.swing.JDialog { setLocation((screenDimension.width - w) / 2, (screenDimension.height - h) / 2); this.setVisible(true); - return artifactStates; + return artifactTypeSelections; } /** @@ -215,20 +221,20 @@ public class ArtifactSelectionDialog extends javax.swing.JDialog { }//GEN-LAST:event_okButtonActionPerformed private void selectAllButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectAllButtonActionPerformed - for (ARTIFACT_TYPE type : artifacts) { - artifactStates.put(type, Boolean.TRUE); + for (BlackboardArtifact.Type type : artifactTypes) { + artifactTypeSelections.put(type, Boolean.TRUE); } artifactList.repaint(); }//GEN-LAST:event_selectAllButtonActionPerformed private void deselectAllButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deselectAllButtonActionPerformed - for (ARTIFACT_TYPE type : artifacts) { - artifactStates.put(type, Boolean.FALSE); + for (BlackboardArtifact.Type type : artifactTypes) { + artifactTypeSelections.put(type, Boolean.FALSE); } artifactList.repaint(); }//GEN-LAST:event_deselectAllButtonActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JList artifactList; + private javax.swing.JList artifactList; private javax.swing.JScrollPane artifactScrollPane; private javax.swing.JButton deselectAllButton; private javax.swing.JButton okButton; @@ -236,16 +242,16 @@ public class ArtifactSelectionDialog extends javax.swing.JDialog { private javax.swing.JLabel titleLabel; // End of variables declaration//GEN-END:variables - private class ArtifactModel implements ListModel { + private class ArtifactModel implements ListModel { @Override public int getSize() { - return artifacts.size(); + return artifactTypes.size(); } @Override - public ARTIFACT_TYPE getElementAt(int index) { - return artifacts.get(index); + public BlackboardArtifact.Type getElementAt(int index) { + return artifactTypes.get(index); } @Override @@ -257,13 +263,13 @@ public class ArtifactSelectionDialog extends javax.swing.JDialog { } } - private class ArtifactRenderer extends JCheckBox implements ListCellRenderer { + private class ArtifactRenderer extends JCheckBox implements ListCellRenderer { @Override - public Component getListCellRendererComponent(JList list, ARTIFACT_TYPE value, int index, boolean isSelected, boolean cellHasFocus) { + public Component getListCellRendererComponent(JList list, BlackboardArtifact.Type value, int index, boolean isSelected, boolean cellHasFocus) { if (value != null) { setEnabled(list.isEnabled()); - setSelected(artifactStates.get(value)); + setSelected(artifactTypeSelections.get(value)); setFont(list.getFont()); setBackground(list.getBackground()); setForeground(list.getForeground()); diff --git a/Core/src/org/sleuthkit/autopsy/report/Bundle.properties b/Core/src/org/sleuthkit/autopsy/report/Bundle.properties index 5e74024afe..d535c310f4 100644 --- a/Core/src/org/sleuthkit/autopsy/report/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/report/Bundle.properties @@ -71,8 +71,6 @@ ReportGenerator.artifactTable.taggedResults.text=Contains results that were tagg ReportGenerator.progress.processing=Now processing {0}... ReportGenerator.msgShow.skippingArtType.title=Skipping artifact type {0} in reports ReportGenerator.msgShow.skippingArtType.msg=Unknown columns to report on -ReportGenerator.msgShow.skippingArtRow.title=Skipping artifact rows for type {0} in reports -ReportGenerator.msgShow.skippingArtRow.msg=Unknown columns to report on ReportGenerator.makeContTagTab.taggedFiles.msg=Contains files that were tagged with one of the following\: ReportGenerator.makeBbArtTagTab.taggedRes.msg=This report only includes results tagged with\: ReportGenerator.tagTable.header.resultType=Result Type diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java index 13aaf200dc..e0d201f4af 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java @@ -34,6 +34,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.HashSet; @@ -41,6 +42,9 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; +import java.util.Set; +import java.util.TreeSet; import java.util.concurrent.ExecutionException; import java.util.logging.Level; import javax.swing.JDialog; @@ -66,6 +70,7 @@ import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase.CaseDbQuery; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; +import org.sleuthkit.datamodel.BlackboardAttribute.Type; /** * Instances of this class use GeneralReportModules, TableReportModules and @@ -83,6 +88,7 @@ class ReportGenerator { private Map tableProgress; private Map generalProgress; private Map fileProgress; + private Map> columnHeaderMap; private String reportPath; private ReportGenerationPanel panel = new ReportGenerationPanel(); @@ -132,18 +138,19 @@ class ReportGenerator { tableProgress = new HashMap<>(); fileProgress = new HashMap<>(); setupProgressPanels(tableModuleStates, generalModuleStates, fileListModuleStates); + this.columnHeaderMap = new HashMap<>(); } /** * Create a ReportProgressPanel for each report generation module selected * by the user. * - * @param tableModuleStates The enabled/disabled state of each - * TableReportModule - * @param generalModuleStates The enabled/disabled state of each - * GeneralReportModule + * @param tableModuleStates The enabled/disabled state of each + * TableReportModule + * @param generalModuleStates The enabled/disabled state of each + * GeneralReportModule * @param fileListModuleStates The enabled/disabled state of each - * FileReportModule + * FileReportModule */ private void setupProgressPanels(Map tableModuleStates, Map generalModuleStates, Map fileListModuleStates) { if (null != tableModuleStates) { @@ -235,11 +242,11 @@ class ReportGenerator { * Run the TableReportModules using a SwingWorker. * * @param artifactTypeSelections the enabled/disabled state of the artifact - * types to be included in the report - * @param tagSelections the enabled/disabled state of the tag names to be - * included in the report + * types to be included in the report + * @param tagSelections the enabled/disabled state of the tag names + * to be included in the report */ - public void generateTableReports(Map artifactTypeSelections, Map tagNameSelections) { + public void generateTableReports(Map artifactTypeSelections, Map tagNameSelections) { if (!tableProgress.isEmpty() && null != artifactTypeSelections) { TableReportsWorker worker = new TableReportsWorker(artifactTypeSelections, tagNameSelections); worker.execute(); @@ -250,7 +257,7 @@ class ReportGenerator { * Run the FileReportModules using a SwingWorker. * * @param enabledInfo the Information that should be included about each - * file in the report. + * file in the report. */ public void generateFileListReports(Map enabledInfo) { if (!fileProgress.isEmpty() && null != enabledInfo) { @@ -420,19 +427,19 @@ class ReportGenerator { private class TableReportsWorker extends SwingWorker { private List tableModules = new ArrayList<>(); - private List artifactTypes = new ArrayList<>(); + private List artifactTypes = new ArrayList<>(); private HashSet tagNamesFilter = new HashSet<>(); private List images = new ArrayList<>(); - TableReportsWorker(Map artifactTypeSelections, Map tagNameSelections) { + TableReportsWorker(Map artifactTypeSelections, Map tagNameSelections) { // Get the report modules selected by the user. for (Entry entry : tableProgress.entrySet()) { tableModules.add(entry.getKey()); } // Get the artifact types selected by the user. - for (Entry entry : artifactTypeSelections.entrySet()) { + for (Entry entry : artifactTypeSelections.entrySet()) { if (entry.getValue()) { artifactTypes.add(entry.getKey()); } @@ -457,7 +464,7 @@ class ReportGenerator { module.startReport(reportPath); progress.start(); progress.setIndeterminate(false); - progress.setMaximumProgress(ARTIFACT_TYPE.values().length + 2); // +2 for content and blackboard artifact tags + progress.setMaximumProgress(this.artifactTypes.size() + 2); // +2 for content and blackboard artifact tags } } @@ -492,7 +499,7 @@ class ReportGenerator { } // Add a table to the report for every enabled blackboard artifact type. - for (ARTIFACT_TYPE type : artifactTypes) { + for (BlackboardArtifact.Type type : artifactTypes) { // Check for cancellaton. removeCancelledTableReportModules(); if (tableModules.isEmpty()) { @@ -506,62 +513,61 @@ class ReportGenerator { } // Keyword hits and hashset hit artifacts get special handling. - if (type.equals(ARTIFACT_TYPE.TSK_KEYWORD_HIT)) { + if (type.getTypeID() == ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) { writeKeywordHits(tableModules, comment.toString(), tagNamesFilter); continue; - } else if (type.equals(ARTIFACT_TYPE.TSK_HASHSET_HIT)) { + } else if (type.getTypeID() == ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID()) { writeHashsetHits(tableModules, comment.toString(), tagNamesFilter); continue; } - List unsortedArtifacts = getFilteredArtifacts(type, tagNamesFilter); + List artifactList = getFilteredArtifacts(type, tagNamesFilter); - if (unsortedArtifacts.isEmpty()) { + if (artifactList.isEmpty()) { continue; } - // The most efficient way to sort all the Artifacts is to add them to a List, and then - // sort that List based off a Comparator. Adding to a TreeMap/Set/List sorts the list - // each time an element is added, which adds unnecessary overhead if we only need it sorted once. - Collections.sort(unsortedArtifacts); - - // Get the column headers appropriate for the artifact type. /* - * @@@ BC: Seems like a better design here would be to have a - * method that takes in the artifact as an argument and returns - * the attributes. We then use that to make the headers and to - * make each row afterwards so that we don't have - * artifact-specific logic in both getArtifactTableCoumnHeaders - * and ArtifactData.getRow() + Gets all of the attribute types of this artifact type by adding + all of the types to a set */ - List columnHeaders = getArtifactTableColumnHeaders(type.getTypeID()); - if (columnHeaders == null) { - // @@@ Hack to prevent system from hanging. Better solution is to merge all attributes into a single column or analyze the artifacts to find out how many are needed. + Set attrTypeSet = new TreeSet<>((Type o1, Type o2) -> o1.getDisplayName().compareTo(o2.getDisplayName())); + for (ArtifactData data : artifactList) { + List attributes = data.getAttributes(); + for (BlackboardAttribute attribute : attributes) { + attrTypeSet.add(attribute.getAttributeType()); + } + } + // Get the columns appropriate for the artifact type. This is + // used to get the data that will be in the cells below based on + // type, and display the column headers. + List columns = getArtifactTableColumns(type.getTypeID(), attrTypeSet); + if (columns.isEmpty()) { continue; } + ReportGenerator.this.columnHeaderMap.put(type.getTypeID(), columns); + + // The artifact list is sorted now, as getting the row data is + // dependent on having the columns, which is necessary for + // sorting. + Collections.sort(artifactList); + List columnHeaderNames = new ArrayList<>(); + for (Column currColumn : columns) { + columnHeaderNames.add(currColumn.getColumnHeader()); + } for (TableReportModule module : tableModules) { module.startDataType(type.getDisplayName(), comment.toString()); - module.startTable(columnHeaders); + module.startTable(columnHeaderNames); } - - boolean msgSent = false; - for (ArtifactData artifactData : unsortedArtifacts) { + for (ArtifactData artifactData : artifactList) { // Add the row data to all of the reports. for (TableReportModule module : tableModules) { - // Get the row data for this type of artifact. + // Get the row data for this artifact, and has the + // module add it. List rowData = artifactData.getRow(); if (rowData.isEmpty()) { - if (msgSent == false) { - MessageNotifyUtil.Notify.show(NbBundle.getMessage(this.getClass(), - "ReportGenerator.msgShow.skippingArtRow.title", - type), - NbBundle.getMessage(this.getClass(), - "ReportGenerator.msgShow.skippingArtRow.msg"), - MessageNotifyUtil.MessageType.ERROR); - msgSent = true; - } continue; } @@ -870,15 +876,15 @@ class ReportGenerator { * Get a List of the artifacts and data of the given type that pass the * given Tag Filter. * - * @param type The artifact type to get + * @param type The artifact type to get * @param tagNamesFilter The tag names that should be included. * * @return a list of the filtered tags. */ - private List getFilteredArtifacts(ARTIFACT_TYPE type, HashSet tagNamesFilter) { + private List getFilteredArtifacts(BlackboardArtifact.Type type, HashSet tagNamesFilter) { List artifacts = new ArrayList<>(); try { - for (BlackboardArtifact artifact : skCase.getBlackboardArtifacts(type)) { + for (BlackboardArtifact artifact : skCase.getBlackboardArtifacts(type.getTypeID())) { List tags = Case.getCurrentCase().getServices().getTagsManager().getBlackboardArtifactTagsByArtifact(artifact); HashSet uniqueTagNames = new HashSet<>(); for (BlackboardArtifactTag tag : tags) { @@ -1046,7 +1052,11 @@ class ReportGenerator { currentKeyword = keyword; for (TableReportModule module : tableModules) { module.addSetElement(currentKeyword); - module.startTable(getArtifactTableColumnHeaders(ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID())); + List columnHeaderNames = new ArrayList<>(); + columnHeaderNames.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.preview")); + columnHeaderNames.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.srcFile")); + columnHeaderNames.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tags")); + module.startTable(columnHeaderNames); } } @@ -1178,7 +1188,11 @@ class ReportGenerator { currentSet = set; for (TableReportModule module : tableModules) { module.startSet(currentSet); - module.startTable(getArtifactTableColumnHeaders(ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID())); + List columnHeaderNames = new ArrayList<>(); + columnHeaderNames.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.file")); + columnHeaderNames.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.size")); + columnHeaderNames.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tags")); + module.startTable(columnHeaderNames); tableProgress.get(module).updateStatusLabel( NbBundle.getMessage(this.getClass(), "ReportGenerator.progress.processingList", ARTIFACT_TYPE.TSK_HASHSET_HIT.getDisplayName(), currentSet)); @@ -1203,335 +1217,523 @@ class ReportGenerator { } /** - * For a given artifact type ID, return the list of the row titles we're + * For a given artifact type ID, return the list of the columns that we are * reporting on. * - * @param artifactTypeId artifact type ID + * @param artifactTypeId artifact type ID + * @param attributeTypeSet The set of attributeTypeSet available for this + * artifact type * * @return List row titles */ - private List getArtifactTableColumnHeaders(int artifactTypeId) { - ArrayList columnHeaders; + private List getArtifactTableColumns(int artifactTypeId, Set attributeTypeSet) { + ArrayList columns = new ArrayList<>(); - BlackboardArtifact.ARTIFACT_TYPE type = BlackboardArtifact.ARTIFACT_TYPE.fromID(artifactTypeId); - switch (type) { - case TSK_WEB_BOOKMARK: - columnHeaders = new ArrayList<>(Arrays.asList(new String[]{ - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.url"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.title"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateCreated"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.program"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.srcFile")})); - break; - case TSK_WEB_COOKIE: - columnHeaders = new ArrayList<>(Arrays.asList(new String[]{ - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.url"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.name"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.value"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.program"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.srcFile")})); - break; - case TSK_WEB_HISTORY: - columnHeaders = new ArrayList<>(Arrays.asList(new String[]{ - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.url"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateAccessed"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.referrer"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.title"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.program"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.urlDomainDecoded"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.srcFile")})); - break; - case TSK_WEB_DOWNLOAD: - columnHeaders = new ArrayList<>(Arrays.asList(new String[]{ - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dest"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.sourceUrl"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateAccessed"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.program"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.srcFile")})); - break; - case TSK_RECENT_OBJECT: - columnHeaders = new ArrayList<>(Arrays.asList(new String[]{ - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.path"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.srcFile")})); - break; - case TSK_INSTALLED_PROG: - columnHeaders = new ArrayList<>(Arrays.asList(new String[]{ - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.progName"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.instDateTime"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.srcFile")})); - break; - case TSK_KEYWORD_HIT: - columnHeaders = new ArrayList<>(Arrays.asList(new String[]{ - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.preview"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.srcFile")})); - break; - case TSK_HASHSET_HIT: - columnHeaders = new ArrayList<>(Arrays.asList(new String[]{ - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.file"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.size")})); - break; - case TSK_DEVICE_ATTACHED: - columnHeaders = new ArrayList<>(Arrays.asList(new String[]{ - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.devMake"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.devModel"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.deviceId"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.srcFile")})); - break; - case TSK_WEB_SEARCH_QUERY: - columnHeaders = new ArrayList<>(Arrays.asList(new String[]{ - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.text"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.domain"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateAccessed"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.progName"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.srcFile")})); - break; - case TSK_METADATA_EXIF: - columnHeaders = new ArrayList<>(Arrays.asList(new String[]{ - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTaken"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.devManufacturer"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.devModel"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.latitude"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.longitude"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.altitude"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.srcFile")})); - break; - case TSK_CONTACT: - columnHeaders = new ArrayList<>(Arrays.asList(new String[]{ - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.personName"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.phoneNumber"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.phoneNumHome"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.phoneNumOffice"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.phoneNumMobile"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.email"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.srcFile")})); - break; - case TSK_MESSAGE: - columnHeaders = new ArrayList<>(Arrays.asList(new String[]{ - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.msgType"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.direction"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.readStatus"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.fromPhoneNum"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.fromEmail"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.toPhoneNum"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.toEmail"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.subject"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.text"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.srcFile")})); - break; - case TSK_CALLLOG: - columnHeaders = new ArrayList<>(Arrays.asList(new String[]{ - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.personName"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.fromPhoneNum"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.toPhoneNum"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.direction"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.srcFile")})); - break; - case TSK_CALENDAR_ENTRY: - columnHeaders = new ArrayList<>(Arrays.asList(new String[]{ - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.calendarEntryType"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.description"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.startDateTime"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.endDateTime"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.location"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.srcFile")})); - break; - case TSK_SPEED_DIAL_ENTRY: - columnHeaders = new ArrayList<>(Arrays.asList(new String[]{ - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.shortCut"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.personName"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.phoneNumber"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.srcFile")})); - break; - case TSK_BLUETOOTH_PAIRING: - columnHeaders = new ArrayList<>(Arrays.asList(new String[]{ - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.deviceName"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.deviceAddress"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.srcFile")})); - break; - case TSK_GPS_TRACKPOINT: - columnHeaders = new ArrayList<>(Arrays.asList(new String[]{ - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.latitude"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.longitude"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.srcFile")})); - break; - case TSK_GPS_BOOKMARK: - columnHeaders = new ArrayList<>(Arrays.asList(new String[]{ - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.latitude"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.longitude"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.altitude"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.name"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.locationAddress"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.srcFile")})); - break; - case TSK_GPS_LAST_KNOWN_LOCATION: - columnHeaders = new ArrayList<>(Arrays.asList(new String[]{ - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.latitude"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.longitude"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.altitude"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.name"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.locationAddress"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.srcFile")})); - break; - case TSK_GPS_SEARCH: - columnHeaders = new ArrayList<>(Arrays.asList(new String[]{ - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.latitude"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.longitude"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.altitude"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.name"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.locationAddress"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.srcFile")})); - break; - case TSK_SERVICE_ACCOUNT: - columnHeaders = new ArrayList<>(Arrays.asList(new String[]{ - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.category"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.userId"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.password"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.personName"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.appName"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.url"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.appPath"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.description"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.replytoAddress"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.mailServer"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.srcFile")})); - break; - case TSK_ENCRYPTION_DETECTED: - columnHeaders = new ArrayList<>(Arrays.asList(new String[]{ - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.name"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.srcFile")})); - break; - case TSK_EXT_MISMATCH_DETECTED: - columnHeaders = new ArrayList<>(Arrays.asList(new String[]{ - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.file"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.extension.text"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.mimeType.text"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.path")})); - break; - case TSK_OS_INFO: - columnHeaders = new ArrayList<>(Arrays.asList(new String[]{ - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.processorArchitecture.text"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.osName.text"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.osInstallDate.text"), - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.srcFile")})); - break; - case TSK_EMAIL_MSG: - columnHeaders = new ArrayList<>(Arrays.asList(new String[]{ - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskEmailTo"), //TSK_EMAIL_TO - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskEmailFrom"), //TSK_EMAIL_FROM - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskSubject"), //TSK_SUBJECT - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskDateTimeSent"), //TSK_DATETIME_SENT - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskDateTimeRcvd"), //TSK_DATETIME_RCVD - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskPath"), //TSK_PATH - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskEmailCc"), //TSK_EMAIL_CC - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskEmailBcc"), //TSK_EMAIL_BCC - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskMsgId")})); //TSK_MSG_ID - break; - case TSK_INTERESTING_FILE_HIT: - columnHeaders = new ArrayList<>(Arrays.asList(new String[]{ - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskSetName"), //TSK_SET_NAME - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskInterestingFilesCategory"), //TSK_CATEGORY - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskPath")})); //TSK_PATH - break; - case TSK_GPS_ROUTE: - columnHeaders = new ArrayList<>(Arrays.asList(new String[]{ - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskGpsRouteCategory"), //TSK_CATEGORY - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"), //TSK_DATETIME - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.latitudeEnd"), //TSK_GEO_LATITUDE_END - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.longitudeEnd"), //TSK_GEO_LONGITUDE_END - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.latitudeStart"), //TSK_GEO_LATITUDE_START - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.longitudeStart"), //TSK_GEO_LONGITUDE_START - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.name"), //TSK_NAME - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.location"), //TSK_LOCATION - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.program")}));//TSK_PROG_NAME - break; - case TSK_INTERESTING_ARTIFACT_HIT: - columnHeaders = new ArrayList<>(Arrays.asList(new String[]{ - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskSetName"), //TSK_SET_NAME - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.associatedArtifact"), //TSK_ASSOCIATED_ARTIFACT - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.program")})); //TSK_PROG_NAME - break; - case TSK_PROG_RUN: - columnHeaders = new ArrayList<>(Arrays.asList(new String[]{ - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.program"), //TSK_PROG_NAME - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.associatedArtifact"), //TSK_ASSOCIATED_ARTIFACT - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"), //TSK_DATETIME - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.count")})); //TSK_COUNT - break; + // Long switch statement to retain ordering of attribute types that are + // attached to pre-defined artifact types. + if (ARTIFACT_TYPE.TSK_WEB_BOOKMARK.getTypeID() == artifactTypeId) { + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.url"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_URL))); - case TSK_OS_ACCOUNT: - columnHeaders = new ArrayList<>(Arrays.asList(new String[]{ - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.userName"), //TSK_USER_NAME - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.userId")})); //TSK_USER_ID - break; + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.title"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_TITLE))); - case TSK_REMOTE_DRIVE: - columnHeaders = new ArrayList<>(Arrays.asList(new String[]{ - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.localPath"), //TSK_LOCAL_PATH - NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.remotePath")})); //TSK_REMOTE_PATH - break; - default: - return null; - } - columnHeaders.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tags")); + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateCreated"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED))); - return columnHeaders; - } + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.program"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME))); - /** - * Map all BlackboardAttributes' values in a list of BlackboardAttributes to - * each attribute's attribute type ID, using module's dateToString method - * for date/time conversions if a module is supplied. - * - * @param attList list of BlackboardAttributes to be mapped - * @param module the TableReportModule the mapping is for - * - * @return Map of the BlackboardAttributes mapped to their - * attribute type ID - */ - public Map getMappedAttributes(List attList, TableReportModule... module) { - Map attributes = new HashMap<>(); - int size = ATTRIBUTE_TYPE.values().length; - for (int n = 0; n <= size; n++) { - attributes.put(n, ""); - } - for (BlackboardAttribute tempatt : attList) { - String value = ""; - Integer type = tempatt.getAttributeTypeID(); - if (type.equals(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID()) - || type.equals(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID()) - || type.equals(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED.getTypeID()) - || type.equals(ATTRIBUTE_TYPE.TSK_DATETIME_MODIFIED.getTypeID()) - || type.equals(ATTRIBUTE_TYPE.TSK_DATETIME_SENT.getTypeID()) - || type.equals(ATTRIBUTE_TYPE.TSK_DATETIME_RCVD.getTypeID()) - || type.equals(ATTRIBUTE_TYPE.TSK_DATETIME_START.getTypeID()) - || type.equals(ATTRIBUTE_TYPE.TSK_DATETIME_END.getTypeID())) { - if (module.length > 0) { - value = module[0].dateToString(tempatt.getValueLong()); - } else { - SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); - value = sdf.format(new java.util.Date((tempatt.getValueLong() * 1000))); - } - } else { - value = tempatt.getDisplayString(); + } else if (ARTIFACT_TYPE.TSK_WEB_COOKIE.getTypeID() == artifactTypeId) { + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.url"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_URL))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.name"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_NAME))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.value"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_VALUE))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.program"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME))); + + } else if (ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID() == artifactTypeId) { + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.url"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_URL))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateAccessed"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.referrer"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_REFERRER))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.title"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_TITLE))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.program"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.urlDomainDecoded"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_URL_DECODED))); + + } else if (ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID() == artifactTypeId) { + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dest"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.sourceUrl"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_URL))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateAccessed"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.program"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME))); + + } else if (ARTIFACT_TYPE.TSK_RECENT_OBJECT.getTypeID() == artifactTypeId) { + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.path"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME))); + + } else if (ARTIFACT_TYPE.TSK_INSTALLED_PROG.getTypeID() == artifactTypeId) { + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.progName"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.instDateTime"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME))); + + } else if (ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID() == artifactTypeId) { + columns.add(new HeaderOnlyColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.preview"))); + + } else if (ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID() == artifactTypeId) { + columns.add(new SourceFileColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.file"))); + + columns.add(new HeaderOnlyColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.size"))); + + } else if (ARTIFACT_TYPE.TSK_DEVICE_ATTACHED.getTypeID() == artifactTypeId) { + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.devMake"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.devModel"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.deviceId"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_ID))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME))); + + } else if (ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID() == artifactTypeId) { + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.text"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_TEXT))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.domain"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DOMAIN))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateAccessed"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.progName"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME))); + + } else if (ARTIFACT_TYPE.TSK_METADATA_EXIF.getTypeID() == artifactTypeId) { + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTaken"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.devManufacturer"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.devModel"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.latitude"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.longitude"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.altitude"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE))); + + } else if (ARTIFACT_TYPE.TSK_CONTACT.getTypeID() == artifactTypeId) { + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.personName"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_NAME))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.phoneNumber"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.phoneNumHome"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_HOME))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.phoneNumOffice"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_OFFICE))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.phoneNumMobile"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_MOBILE))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.email"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_EMAIL))); + + } else if (ARTIFACT_TYPE.TSK_MESSAGE.getTypeID() == artifactTypeId) { + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.msgType"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.direction"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DIRECTION))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.readStatus"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_READ_STATUS))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.fromPhoneNum"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.fromEmail"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_EMAIL_FROM))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.toPhoneNum"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.toEmail"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_EMAIL_TO))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.subject"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SUBJECT))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.text"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_TEXT))); + + } else if (ARTIFACT_TYPE.TSK_CALLLOG.getTypeID() == artifactTypeId) { + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.personName"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_NAME))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.fromPhoneNum"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.toPhoneNum"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_START))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.direction"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DIRECTION))); + + } else if (ARTIFACT_TYPE.TSK_CALENDAR_ENTRY.getTypeID() == artifactTypeId) { + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.calendarEntryType"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_CALENDAR_ENTRY_TYPE))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.description"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DESCRIPTION))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.startDateTime"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_START))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.endDateTime"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_END))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.location"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_LOCATION))); + + } else if (ARTIFACT_TYPE.TSK_SPEED_DIAL_ENTRY.getTypeID() == artifactTypeId) { + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.shortCut"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SHORTCUT))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.personName"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_NAME_PERSON))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.phoneNumber"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER))); + + } else if (ARTIFACT_TYPE.TSK_BLUETOOTH_PAIRING.getTypeID() == artifactTypeId) { + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.deviceName"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_NAME))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.deviceAddress"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_ID))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME))); + + } else if (ARTIFACT_TYPE.TSK_GPS_TRACKPOINT.getTypeID() == artifactTypeId) { + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.latitude"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.longitude"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME))); + + } else if (ARTIFACT_TYPE.TSK_GPS_BOOKMARK.getTypeID() == artifactTypeId) { + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.latitude"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.longitude"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.altitude"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.name"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_NAME))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.locationAddress"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_LOCATION))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME))); + + } else if (ARTIFACT_TYPE.TSK_GPS_LAST_KNOWN_LOCATION.getTypeID() == artifactTypeId) { + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.latitude"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.longitude"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.altitude"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.name"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_NAME))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.locationAddress"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_LOCATION))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME))); + + } else if (ARTIFACT_TYPE.TSK_GPS_SEARCH.getTypeID() == artifactTypeId) { + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.latitude"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.longitude"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.altitude"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.name"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_NAME))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.locationAddress"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_LOCATION))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME))); + + } else if (ARTIFACT_TYPE.TSK_SERVICE_ACCOUNT.getTypeID() == artifactTypeId) { + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.category"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_CATEGORY))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.userId"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_ID))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.password"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PASSWORD))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.personName"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_NAME))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.appName"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.url"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_URL))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.appPath"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.description"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DESCRIPTION))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.replytoAddress"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_EMAIL_REPLYTO))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.mailServer"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SERVER_NAME))); + + } else if (ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED.getTypeID() == artifactTypeId) { + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.name"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_NAME))); + + } else if (ARTIFACT_TYPE.TSK_EXT_MISMATCH_DETECTED.getTypeID() == artifactTypeId) { + columns.add(new HeaderOnlyColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.file"))); + + columns.add(new HeaderOnlyColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.extension.text"))); + + columns.add(new HeaderOnlyColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.mimeType.text"))); + + columns.add(new HeaderOnlyColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.path"))); + + } else if (ARTIFACT_TYPE.TSK_OS_INFO.getTypeID() == artifactTypeId) { + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.processorArchitecture.text"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROCESSOR_ARCHITECTURE))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.osName.text"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.osInstallDate.text"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME))); + + } else if (ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID() == artifactTypeId) { + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskEmailTo"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_EMAIL_TO))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskEmailFrom"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_EMAIL_FROM))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskSubject"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SUBJECT))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskDateTimeSent"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_SENT))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskDateTimeRcvd"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_RCVD))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskPath"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskEmailCc"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_EMAIL_CC))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskEmailBcc"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_EMAIL_BCC))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskMsgId"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_MSG_ID))); + + } else if (ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID() == artifactTypeId) { + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskSetName"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SET_NAME))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskInterestingFilesCategory"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_CATEGORY))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskPath"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH))); + + } else if (ARTIFACT_TYPE.TSK_GPS_ROUTE.getTypeID() == artifactTypeId) { + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskGpsRouteCategory"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_CATEGORY))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.latitudeEnd"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.longitudeEnd"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_END))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.latitudeStart"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.longitudeStart"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_START))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.name"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_NAME))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.location"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_LOCATION))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.program"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME))); + + } else if (ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID() == artifactTypeId) { + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskSetName"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SET_NAME))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.associatedArtifact"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.program"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME))); + + } else if (ARTIFACT_TYPE.TSK_PROG_RUN.getTypeID() == artifactTypeId) { + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.program"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.associatedArtifact"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.dateTime"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.count"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_COUNT))); + + } else if (ARTIFACT_TYPE.TSK_OS_ACCOUNT.getTypeID() == artifactTypeId) { + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.userName"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_NAME))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.userId"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_ID))); + + } else if (ARTIFACT_TYPE.TSK_REMOTE_DRIVE.getTypeID() == artifactTypeId) { + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.localPath"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_LOCAL_PATH))); + + columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.remotePath"), + new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_REMOTE_PATH))); + } else { + // This is the case that it is a custom type. The reason an else is + // necessary is to make sure that the source file column is added + for (BlackboardAttribute.Type type : attributeTypeSet) { + columns.add(new AttributeColumn(type.getDisplayName(), type)); } + columns.add(new SourceFileColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.srcFile"))); + columns.add(new TaggedResultsColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tags"))); - if (value == null) { - value = ""; - } - value = EscapeUtil.escapeHtml(value); - attributes.put(type, value); + // Short circuits to guarantee that the attribute types aren't added + // twice. + return columns; } - return attributes; + // If it is an attribute column, it removes the attribute type of that + // column from the set, so types are not reported more than once. + for (Column column : columns) { + attributeTypeSet = column.removeTypeFromSet(attributeTypeSet); + } + // Now uses the remaining types in the set to construct columns + for (BlackboardAttribute.Type type : attributeTypeSet) { + columns.add(new AttributeColumn(type.getDisplayName(), type)); + } + // Source file column is added here for ordering purposes. + if (artifactTypeId == ARTIFACT_TYPE.TSK_WEB_BOOKMARK.getTypeID() + || artifactTypeId == ARTIFACT_TYPE.TSK_WEB_COOKIE.getTypeID() + || artifactTypeId == ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID() + || artifactTypeId == ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID() + || artifactTypeId == ARTIFACT_TYPE.TSK_RECENT_OBJECT.getTypeID() + || artifactTypeId == ARTIFACT_TYPE.TSK_INSTALLED_PROG.getTypeID() + || artifactTypeId == ARTIFACT_TYPE.TSK_DEVICE_ATTACHED.getTypeID() + || artifactTypeId == ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID() + || artifactTypeId == ARTIFACT_TYPE.TSK_METADATA_EXIF.getTypeID() + || artifactTypeId == ARTIFACT_TYPE.TSK_CONTACT.getTypeID() + || artifactTypeId == ARTIFACT_TYPE.TSK_MESSAGE.getTypeID() + || artifactTypeId == ARTIFACT_TYPE.TSK_CALLLOG.getTypeID() + || artifactTypeId == ARTIFACT_TYPE.TSK_CALENDAR_ENTRY.getTypeID() + || artifactTypeId == ARTIFACT_TYPE.TSK_SPEED_DIAL_ENTRY.getTypeID() + || artifactTypeId == ARTIFACT_TYPE.TSK_BLUETOOTH_PAIRING.getTypeID() + || artifactTypeId == ARTIFACT_TYPE.TSK_GPS_TRACKPOINT.getTypeID() + || artifactTypeId == ARTIFACT_TYPE.TSK_GPS_BOOKMARK.getTypeID() + || artifactTypeId == ARTIFACT_TYPE.TSK_GPS_LAST_KNOWN_LOCATION.getTypeID() + || artifactTypeId == ARTIFACT_TYPE.TSK_GPS_SEARCH.getTypeID() + || artifactTypeId == ARTIFACT_TYPE.TSK_SERVICE_ACCOUNT.getTypeID() + || artifactTypeId == ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED.getTypeID() + || artifactTypeId == ARTIFACT_TYPE.TSK_OS_INFO.getTypeID()) { + columns.add(new SourceFileColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.srcFile"))); + } + columns.add(new TaggedResultsColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tags"))); + + return columns; } /** @@ -1570,6 +1772,7 @@ class ReportGenerator { logger.log(Level.WARNING, "Failed to get Abstract File by ID.", ex); //NON-NLS } return ""; + } /** @@ -1611,7 +1814,8 @@ class ReportGenerator { /** * Compares ArtifactData objects by the first attribute they have in - * common in their List. + * common in their List. Should only be used on two + * artifacts of the same type * * If all attributes are the same, they are assumed duplicates and are * compared by their artifact id. Should only be used with attributes of @@ -1627,22 +1831,32 @@ class ReportGenerator { return compare; } } - // If all attributes are the same, they're most likely duplicates so sort by artifact ID return ((Long) this.getArtifactID()).compareTo((Long) otherArtifactData.getArtifactID()); } /** * Get the values for each row in the table report. + * + * the value types of custom artifacts + * + * @return A list of string representing the data for this artifact. */ public List getRow() { if (rowData == null) { try { rowData = getOrderedRowDataAsStrings(); - // replace null values if attribute was not defined - for (int i = 0; i < rowData.size(); i++) { - if (rowData.get(i) == null) { - rowData.set(i, ""); + // If else is done so that row data is not set before + // columns are added to the hash map. + if (rowData.size() > 0) { + // replace null values if attribute was not defined + for (int i = 0; i < rowData.size(); i++) { + if (rowData.get(i) == null) { + rowData.set(i, ""); + } } + } else { + rowData = null; + return new ArrayList<>(); } } catch (TskCoreException ex) { errorList.add( @@ -1659,274 +1873,66 @@ class ReportGenerator { * correct order to be written to the report. * * @return List row values. Values could be null if attribute is - * not defined in artifact + * not defined in artifact * * @throws TskCoreException */ private List getOrderedRowDataAsStrings() throws TskCoreException { - Map mappedAttributes = getMappedAttributes(); + List orderedRowData = new ArrayList<>(); - BlackboardArtifact.ARTIFACT_TYPE type = BlackboardArtifact.ARTIFACT_TYPE.fromID(getArtifact().getArtifactTypeID()); - switch (type) { - case TSK_WEB_BOOKMARK: - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_URL.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_TITLE.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID())); - orderedRowData.add(getFileUniquePath(getObjectID())); - break; - case TSK_WEB_COOKIE: - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_URL.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_NAME.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_VALUE.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID())); - orderedRowData.add(getFileUniquePath(getObjectID())); - break; - case TSK_WEB_HISTORY: - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_URL.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_REFERRER.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_TITLE.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID())); - orderedRowData.add(getFileUniquePath(getObjectID())); - break; - case TSK_WEB_DOWNLOAD: - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_PATH.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_URL.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID())); - orderedRowData.add(getFileUniquePath(getObjectID())); - break; - case TSK_RECENT_OBJECT: - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_PATH.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID())); - orderedRowData.add(getFileUniquePath(getObjectID())); - break; - case TSK_INSTALLED_PROG: - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID())); - orderedRowData.add(getFileUniquePath(getObjectID())); - break; - case TSK_DEVICE_ATTACHED: - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_DEVICE_ID.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID())); - orderedRowData.add(getFileUniquePath(getObjectID())); - break; - case TSK_WEB_SEARCH_QUERY: - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_TEXT.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID())); - orderedRowData.add(getFileUniquePath(getObjectID())); - break; - case TSK_METADATA_EXIF: - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE.getTypeID())); - orderedRowData.add(getFileUniquePath(getObjectID())); - break; - case TSK_CONTACT: - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_NAME.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_HOME.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_OFFICE.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_MOBILE.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_EMAIL.getTypeID())); - orderedRowData.add(getFileUniquePath(getObjectID())); - break; - case TSK_MESSAGE: - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_DIRECTION.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_READ_STATUS.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_EMAIL_FROM.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_EMAIL_TO.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_SUBJECT.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_TEXT.getTypeID())); - orderedRowData.add(getFileUniquePath(getObjectID())); - break; - case TSK_CALLLOG: - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_NAME.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_DATETIME_START.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_DIRECTION.getTypeID())); - orderedRowData.add(getFileUniquePath(getObjectID())); - break; - case TSK_CALENDAR_ENTRY: - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_CALENDAR_ENTRY_TYPE.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_DESCRIPTION.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_DATETIME_START.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_DATETIME_END.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_LOCATION.getTypeID())); - orderedRowData.add(getFileUniquePath(getObjectID())); - break; - case TSK_SPEED_DIAL_ENTRY: - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_SHORTCUT.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_NAME_PERSON.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER.getTypeID())); - orderedRowData.add(getFileUniquePath(getObjectID())); - break; - case TSK_BLUETOOTH_PAIRING: - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_DEVICE_NAME.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_DEVICE_ID.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID())); - orderedRowData.add(getFileUniquePath(getObjectID())); - break; - case TSK_GPS_TRACKPOINT: - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID())); - orderedRowData.add(getFileUniquePath(getObjectID())); - break; - case TSK_GPS_BOOKMARK: - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_NAME.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_LOCATION.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID())); - orderedRowData.add(getFileUniquePath(getObjectID())); - break; - case TSK_GPS_LAST_KNOWN_LOCATION: - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_NAME.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_LOCATION.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID())); - orderedRowData.add(getFileUniquePath(getObjectID())); - break; - case TSK_GPS_SEARCH: - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_NAME.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_LOCATION.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID())); - orderedRowData.add(getFileUniquePath(getObjectID())); - break; - case TSK_SERVICE_ACCOUNT: - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_CATEGORY.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_USER_ID.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_PASSWORD.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_NAME.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_URL.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_PATH.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_DESCRIPTION.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_EMAIL_REPLYTO.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_SERVER_NAME.getTypeID())); - orderedRowData.add(getFileUniquePath(getObjectID())); - break; - case TSK_TOOL_OUTPUT: - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_TEXT.getTypeID())); - orderedRowData.add(getFileUniquePath(getObjectID())); - break; - case TSK_ENCRYPTION_DETECTED: - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_NAME.getTypeID())); - orderedRowData.add(getFileUniquePath(getObjectID())); - break; - case TSK_EXT_MISMATCH_DETECTED: - AbstractFile file = skCase.getAbstractFileById(getObjectID()); - if (file != null) { - orderedRowData.add(file.getName()); - orderedRowData.add(file.getNameExtension()); - String mimeType = file.getMIMEType(); - if(mimeType == null) { - orderedRowData.add(""); - } - else { - orderedRowData.add(mimeType); - } - orderedRowData.add(file.getUniquePath()); + if (ARTIFACT_TYPE.TSK_EXT_MISMATCH_DETECTED.getTypeID() == getArtifact().getArtifactTypeID()) { + AbstractFile file = skCase.getAbstractFileById(getObjectID()); + if (file != null) { + orderedRowData.add(file.getName()); + orderedRowData.add(file.getNameExtension()); + String mimeType = file.getMIMEType(); + if (mimeType == null) { + orderedRowData.add(""); } else { - // Make empty rows to make sure the formatting is correct - orderedRowData.add(null); - orderedRowData.add(null); - orderedRowData.add(null); - orderedRowData.add(null); + orderedRowData.add(mimeType); } - break; - case TSK_OS_INFO: - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_PROCESSOR_ARCHITECTURE.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID())); - orderedRowData.add(getFileUniquePath(getObjectID())); - break; - case TSK_EMAIL_MSG: - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_EMAIL_TO.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_EMAIL_FROM.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_SUBJECT.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_DATETIME_SENT.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_DATETIME_RCVD.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_PATH.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_EMAIL_CC.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_EMAIL_BCC.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_MSG_ID.getTypeID())); - break; - case TSK_INTERESTING_FILE_HIT: - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_CATEGORY.getTypeID())); - String pathToShow = mappedAttributes.get(ATTRIBUTE_TYPE.TSK_PATH.getTypeID()); - if (pathToShow.isEmpty()) { - pathToShow = getFileUniquePath(getObjectID()); + orderedRowData.add(file.getUniquePath()); + } else { + // Make empty rows to make sure the formatting is correct + orderedRowData.add(null); + orderedRowData.add(null); + orderedRowData.add(null); + orderedRowData.add(null); + } + orderedRowData.add(makeCommaSeparatedList(getTags())); + + } else if (ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID() == getArtifact().getArtifactTypeID()) { + String[] attributeDataArray = new String[3]; + // Array is used so that the order of the attributes is + // maintained. + for (BlackboardAttribute attr : attributes) { + if (attr.getAttributeType().equals(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SET_NAME))) { + attributeDataArray[0] = attr.getDisplayString(); + } else if (attr.getAttributeType().equals(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_CATEGORY))) { + attributeDataArray[1] = attr.getDisplayString(); + } else if (attr.getAttributeType().equals(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH))) { + String pathToShow = attr.getDisplayString(); + if (pathToShow.isEmpty()) { + pathToShow = getFileUniquePath(getObjectID()); + } + attributeDataArray[2] = pathToShow; } - orderedRowData.add(pathToShow); - break; - case TSK_GPS_ROUTE: - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_CATEGORY.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_END.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_START.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_NAME.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_LOCATION.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID())); - break; - case TSK_INTERESTING_ARTIFACT_HIT: - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID())); - break; - case TSK_PROG_RUN: - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_COUNT.getTypeID())); - break; - case TSK_OS_ACCOUNT: - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_USER_NAME.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_USER_ID.getTypeID())); - break; - case TSK_REMOTE_DRIVE: - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_LOCAL_PATH.getTypeID())); - orderedRowData.add(mappedAttributes.get(ATTRIBUTE_TYPE.TSK_REMOTE_PATH.getTypeID())); - break; + } + orderedRowData.addAll(Arrays.asList(attributeDataArray)); + orderedRowData.add(makeCommaSeparatedList(getTags())); + + } else { + if (ReportGenerator.this.columnHeaderMap.containsKey(this.artifact.getArtifactTypeID())) { + + for (Column currColumn : ReportGenerator.this.columnHeaderMap.get(this.artifact.getArtifactTypeID())) { + String cellData = currColumn.getCellData(this); + orderedRowData.add(cellData); + } + } } - orderedRowData.add(makeCommaSeparatedList(getTags())); return orderedRowData; } - - /** - * Returns a mapping of Attribute Type ID to the String representation - * of an Attribute Value. - */ - private Map getMappedAttributes() { - return ReportGenerator.this.getMappedAttributes(attributes); - } } /** @@ -1955,6 +1961,133 @@ class ReportGenerator { } return uniqueTagNames; + } + private interface Column { + + String getColumnHeader(); + + String getCellData(ArtifactData artData); + + Set removeTypeFromSet(Set types); + } + + private class AttributeColumn implements Column { + + private String columnHeader; + private BlackboardAttribute.Type attributeType; + + /** + * Constructs an ArtifactCell + * + * @param columnHeader The header text of this column + * @param attributeType The attribute type associated with this column + */ + AttributeColumn(String columnHeader, BlackboardAttribute.Type attributeType) { + this.columnHeader = Objects.requireNonNull(columnHeader); + this.attributeType = attributeType; + } + + @Override + public String getColumnHeader() { + return this.columnHeader; + } + + @Override + public String getCellData(ArtifactData artData) { + List attributes = artData.getAttributes(); + for (BlackboardAttribute attribute : attributes) { + if (attribute.getAttributeType().equals(this.attributeType)) { + return attribute.getDisplayString(); + } + } + return ""; + } + + @Override + public Set removeTypeFromSet(Set types) { + types.remove(this.attributeType); + return types; + } + } + + private class SourceFileColumn implements Column { + + private String columnHeader; + + SourceFileColumn(String columnHeader) { + this.columnHeader = columnHeader; + } + + @Override + public String getColumnHeader() { + return this.columnHeader; + } + + @Override + public String getCellData(ArtifactData artData) { + return getFileUniquePath(artData.getObjectID()); + /*else if (this.columnHeader.equals(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tags"))) { + return makeCommaSeparatedList(artData.getTags()); + } + return "";*/ + } + + @Override + public Set removeTypeFromSet(Set types) { + // This column doesn't have a type, so nothing to remove + return types; + } + } + + private class TaggedResultsColumn implements Column { + + private String columnHeader; + + TaggedResultsColumn(String columnHeader) { + this.columnHeader = columnHeader; + } + + @Override + public String getColumnHeader() { + return this.columnHeader; + } + + @Override + public String getCellData(ArtifactData artData) { + return makeCommaSeparatedList(artData.getTags()); + } + + @Override + public Set removeTypeFromSet(Set types) { + // This column doesn't have a type, so nothing to remove + return types; + } + } + + private class HeaderOnlyColumn implements Column { + + private String columnHeader; + + HeaderOnlyColumn(String columnHeader) { + this.columnHeader = columnHeader; + } + + @Override + public String getColumnHeader() { + return columnHeader; + } + + @Override + public String getCellData(ArtifactData artData) { + throw new UnsupportedOperationException("Cannot get cell data of unspecified column"); + } + + @Override + public Set removeTypeFromSet(Set types) { + // This column doesn't have a type, so nothing to remove + return types; + } + } } diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java index d7a7014022..196f770ca7 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java @@ -262,7 +262,6 @@ class ReportHTML implements TableReportModule { break; } } else { // no defined artifact found for this dataType - logger.log(Level.WARNING, "useDataTypeIcon: no artifact found for data type = " + dataType); //NON-NLS in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/star.png"); //NON-NLS iconFileName = "star.png"; //NON-NLS iconFilePath = path + File.separator + iconFileName; @@ -984,8 +983,8 @@ class ReportHTML implements TableReportModule { StringBuilder head = new StringBuilder(); head.append("\n\n").append( //NON-NLS NbBundle.getMessage(this.getClass(), "ReportHTML.writeSum.title")).append("\n"); //NON-NLS - head.append("