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/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 7b10bdbea9..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/UserArtifacts/UserArtifactIngestModule.java +++ /dev/null @@ -1,150 +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 - List currArtifacts = Case.getCurrentCase().getSleuthkitCase().getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF); - BlackboardArtifact art1 = currArtifacts.size() == 0 ? null : currArtifacts.get(0); - BlackboardArtifact art2; - if (art1 == null) { - 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().getSleuthkitCase().getAttributeType("Test8"); - if (attributeType == null) { - attributeType = Case.getCurrentCase().getServices().getBlackboard().addAttributeType("Test8", TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.LONG, "Header6"); - } - BlackboardAttribute.Type attributeType2 = Case.getCurrentCase().getSleuthkitCase().getAttributeType("Test9"); - if (attributeType2 == null) { - attributeType2 = Case.getCurrentCase().getServices().getBlackboard().addAttributeType("Test9", TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME, "Header7"); - - } - BlackboardAttribute.Type attributeType3 = Case.getCurrentCase().getSleuthkitCase().getAttributeType("Test0"); - if (attributeType3 == null) { - attributeType3 = Case.getCurrentCase().getServices().getBlackboard().addAttributeType("Test0", TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, "Header8"); - - } - BlackboardAttribute.Type attributeType4 = Case.getCurrentCase().getSleuthkitCase().getAttributeType("TestA"); - if (attributeType4 == null) { - attributeType4 = Case.getCurrentCase().getServices().getBlackboard().addAttributeType("TestA", TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.INTEGER, "Header9"); - - } - BlackboardAttribute.Type attributeType5 = Case.getCurrentCase().getSleuthkitCase().getAttributeType("TestB"); - if (attributeType5 == null) { - attributeType5 = Case.getCurrentCase().getServices().getBlackboard().addAttributeType("TestB", TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DOUBLE, "Header0"); - - } - BlackboardAttribute.Type attributeType6 = Case.getCurrentCase().getSleuthkitCase().getAttributeType("TestC"); - if (attributeType6 == null) { - attributeType6 = Case.getCurrentCase().getServices().getBlackboard().addAttributeType("TestC", TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.BYTE, "HeaderA"); - - } - art1.addAttribute(new BlackboardAttribute(attributeType, - UserArtifactIngestModuleFactory.getModuleName(), 12345678L)); - art1.addAttribute(new BlackboardAttribute(attributeType2, - UserArtifactIngestModuleFactory.getModuleName(), 1457105587962L)); - art1.addAttribute(new BlackboardAttribute(attributeType3, - UserArtifactIngestModuleFactory.getModuleName(), "STRING VALUE TEST")); - art1.addAttribute(new BlackboardAttribute(attributeType4, - UserArtifactIngestModuleFactory.getModuleName(), 1234)); - art1.addAttribute(new BlackboardAttribute(attributeType5, - UserArtifactIngestModuleFactory.getModuleName(), 1234.5678D)); - byte[] bytes = new byte[2]; - bytes[0] = 12; - bytes[1] = 100; - art1.addAttribute(new BlackboardAttribute(attributeType6, - UserArtifactIngestModuleFactory.getModuleName(), bytes)); - art2.addAttribute(new BlackboardAttribute(attributeType2, - UserArtifactIngestModuleFactory.getModuleName(), 1457105587962L)); - art2.addAttribute(new BlackboardAttribute(attributeType, - UserArtifactIngestModuleFactory.getModuleName(), 12345678L)); - art2.addAttribute(new BlackboardAttribute(attributeType3, - UserArtifactIngestModuleFactory.getModuleName(), "STRING VALUE TEST")); - art2.addAttribute(new BlackboardAttribute(attributeType4, - UserArtifactIngestModuleFactory.getModuleName(), 1234)); - art2.addAttribute(new BlackboardAttribute(attributeType5, - UserArtifactIngestModuleFactory.getModuleName(), 1234.5678D)); - art2.addAttribute(new BlackboardAttribute(attributeType6, - UserArtifactIngestModuleFactory.getModuleName(), bytes)); - 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().getSleuthkitCase().getArtifactType("FINAL TEST a"); - type2 = Case.getCurrentCase().getSleuthkitCase().getArtifactType("FINAL TEST b"); - if (type1 == null) { - type1 = Case.getCurrentCase().getServices().getBlackboard().addArtifactType("FINAL TEST a", "FINAL TEST a"); //NON-NLS - } - if (type2 == null) { - type2 = Case.getCurrentCase().getServices().getBlackboard().addArtifactType("FINAL TEST b", "FINAL TEST b"); //NON-NLS - } - } catch (BlackboardException | TskCoreException 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 82ff77b269..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/UserArtifacts/UserArtifactIngestModuleFactory.java +++ /dev/null @@ -1,63 +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.openide.util.lookup.ServiceProvider; -import org.python.apache.xmlcommons.Version; -import org.sleuthkit.autopsy.ingest.DataSourceIngestModule; -import org.sleuthkit.autopsy.ingest.IngestModuleFactory; -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/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/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..de807b0672 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,195 @@ 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 +511,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 +536,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 +546,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 +567,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 +578,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 +599,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 +618,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 +630,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 +650,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 +687,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 +732,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 +753,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 +774,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 +810,7 @@ final class FilesSet { */ private static class CaseInsensitiveStringComparisionMatcher implements TextMatcher { + private static final long serialVersionUID = 1L; private final String textToMatch; /** @@ -620,6 +854,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 +899,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..fb52eb0354 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." + }) + + 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) { + 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) { + 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..fbd7a72263 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,55 @@ 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()); } + private void customInit() { + 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 +146,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 +192,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 +257,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 +288,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 +381,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 +406,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 +470,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 +479,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 +503,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 +525,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 +593,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 +607,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 +629,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 +666,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 +682,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 +698,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 +731,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 +889,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 +932,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 +959,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 +974,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 +995,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/NEWS.txt b/NEWS.txt index cf692b5ed3..53c2d3fb0c 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -10,7 +10,7 @@ Improvements: - New Embedded File Extractor module that incorporates ZIP file module and extracts images from Office documents - Views area counts updates when ZIP files and such are found - Updates to python scripting for new version of Python, scripts are reloaded each time ingest is run, and errors are better shown. -- Updated right click actions to be consistent accross all file types +- Updated right click actions to be consistent across all file types - Changed logic of Interesting Files module to look for substrings of parent path. - Lots of minor fixes and enhancements @@ -18,7 +18,7 @@ Improvements: ---------------- VERSION 3.1.2 -------------- Improvements: - New PhotoRec carving ingest module -- Regripper output is avaiable as a report instead of TOOL_OUTPUT artifact +- Regripper output is available as a report instead of TOOL_OUTPUT artifact - Updated version of RegRipper - New STIX/Cybox report module (manually run after image has been analyzed) - File type module supports user defined file types and can alert when they are found @@ -71,12 +71,12 @@ Improvements: - Times can be displayed in local time or GMT - New "EnCase-style" report that lists files and metadata in tab delimited file - Changed report wizard to make one report at a time -- report improvements (only regnerate if data exists) +- report improvements (only regenerate if data exists) - more error messages if recent activity module fails - more error checking in recent activity module and don't bail as quickly - Cleanup of recent activity module - better handle if ingest module throws exception during init() -- do not run ingest if any module faile to init() +- do not run ingest if any module failed to init() - Added FILE_DONE event to ingest manager - Added search engine parsers for linkedin, twitter, and facebook - HTML text is better formatted @@ -484,7 +484,7 @@ Autopsy Windows 03/05/05: Update: Added SSN and credit card seach patterns from Jerry Shenk. -03/05/05: Update: Added temporal data when a note is creaed. +03/05/05: Update: Added temporal data when a note is created. 03/11/05: Update: Changed to new TSK names for srch_strings and img_stat @@ -531,7 +531,7 @@ directory box, the recover bit is set so the full contents are shown. 03/29/04: Update: Changed text for the data integrity option when adding a new image. -04/20/04: Bug Fix: Fixed error that occured when data browsing with +04/20/04: Bug Fix: Fixed error that occurred when data browsing with a raw or swap image. The TSK usage for these file system types was inconsistent and it was fixed in version 1.69. (BUG: 925382). (Reported by Harald Katzer) @@ -670,7 +670,7 @@ number of bytes. than once. (Paul Bakker) 06/01/03: Bug Fix: Some keyword searches with $ in it were failing 06/01/03: Update: Keyword searches are now saved to a file and can be - found in the keyword seach main menu + found in the keyword search main menu 06/01/03: Update: Changed the format a little of the keyword search menu 06/01/03: Update: Added grep cheat sheet @@ -713,7 +713,7 @@ number of bytes. 03/20/03: Update: passwd and group files are now imported in timelines by selecting the image - no more inode values 03/20/03: Update: Cleaned up HTML code in timeline section -03/21/03: Update: Added '-z' flag to usage of 'file' so that comressed +03/21/03: Update: Added '-z' flag to usage of 'file' so that compressed files are opened. 03/21/03: Bug Fix: Some special values needed to be escaped in the grep keyword search (for non regular expressions) (\.]^$"-). @@ -770,7 +770,7 @@ Interface Changes: --------------------------- Version 1.61 --------------------------------- -08/28/02: Update: White space is allowed at the begining of the morgue file +08/28/02: Update: White space is allowed at the beginning of the morgue file 08/28/02: Bug Fix: No error is generated if md5.txt does not exist from main menu 08/28/02: Update: Improved error messages diff --git a/README.md b/README.md index 324661c8fa..fc0a280a40 100644 --- a/README.md +++ b/README.md @@ -1,43 +1,36 @@ -# Autopsy 4.0 +Autopsy 4 + http://www.sleuthkit.org/ -March 3, 2016 - +March 15, 2016 ##OVERVIEW Autopsy is a graphical interface to The Sleuth Kit and other open source digital forensics tools. -Autopsy 4 (and 3) are a complete rewrite from Autopsy 2, and none of this document is relevant to Autopsy 2. +Autopsy 3 was a complete rewrite from Autopsy 2 to make it Java-based. +Autopsy 4 improves on Autopsy 3 by supporting collaboration on a single case by multiple users. Although Autopsy is designed to be cross-platform (Windows, Linux, MacOSX), the current version is fully functional and fully tested only on Windows. -You can run Autopsy 4 on Linux and OS X, but it must be built from source code. +We have run it on XP, Vista, and Windows 7 with no problems. -Autopsy 3 and 4 source code are distributed under a Apache 2 license. The package contains libraries that may have different licenses. +Autopsy 4 is released under the Apache 2.0 license. +Some libraries Autopsy uses may have different, but similar, open source licenses. ##INSTALLATION -All Autopsy dependencies are bundled with the installer provided. -For Autopsy 3, there is no need for manual installation of additional dependencies if the installer is used. -The current version of Autopsy 4 is distributed on sleuthkit.org only as a Windows installer. It can run on Linux and OS X, but requires some manual setup. To install Autopsy, perform the following steps: - -* Run the Autopsy msi file -* If Windows prompts with User Account Control, click Yes -* Click through the dialog boxes until you click a button that says Finish -* Autopsy should now be fully installed - +For a Windows installation, all Autopsy dependencies are bundled with the installer provided. +There is no need for manual installation of additional dependencies if the Windows installer is used. If you want the Japanese localized version, you must have the Japanese language pack (http://support.microsoft.com/kb/972813) installed and the default locale set to JA. (http://windows.microsoft.com/en-us/windows/change-system-locale#1TC=windows-7). -Refer to the next section for additional info on third-party software requirements to run Autopsy without installer. - Refer to the KNOWN_ISSUES.txt file for known bugs that could cause investigation problems. ##SUPPORT -There is a built-in help system in Autopsy once you get it started. There is also a QuickStart Guide that came with the installer. +There is a built-in help system in Autopsy once you get it started. There is also a QuickStart Guide that comes with the installer. Send any bug reports or feature requests to the sleuthkit-users e-mail list. http://www.sleuthkit.org/support.php @@ -47,26 +40,27 @@ Send any bug reports or feature requests to the sleuthkit-users e-mail list. The Autopsy code is released under the Apache License, Version 2. See LICENSE-2.0.txt for details. + ##EMBEDDED SOFTWARE -This section lists the software components and libraries that are used inside of -Autopsy. These tools are bundled with the installer, unless specified otherwise. +This section lists the software components and libraries that are used by of +Autopsy. These tools are bundled with the Windows installer, unless specified otherwise. JRE (Java Runtime Environment) 1.8 - Web page: http://www.oracle.com/technetwork/java/index.html - License: http://www.oracle.com/technetwork/java/javase/terms/license/index.html -Netbeans 7.3 RCP platform and .jar files bundled with the platform +Netbeans 8.0.2 RCP platform and .jar files bundled with the platform - Web page: http://netbeans.org/features/platform/ - License: -http://services.netbeans.org/downloads/licence/nb-7.0-final-2011-04-20-license.txt +https://netbeans.org/downloads/jdk-bundle/8.0.2/nb802-LICENSE.txt Sleuth Kit for analyzing disk images. - Web page: http://www.sleuthkit.org/sleuthkit/ - License: http://sleuthkit.org/sleuthkit/licenses.php Libewf for opening E01 files -- Web page: http://sourceforge.net/projects/libewf/ +- Web page: https://github.com/libyal/libewf - License: http://www.gnu.org/licenses/lgpl.html zlib for opening E01 files @@ -123,7 +117,7 @@ ImgScalr 4.2 for image resizing in image viewers - License: http://www.thebuzzmedia.com/software/imgscalr-java-image-scaling-library/#license -##EMBEDED RESOURCES +##EMBEDDED RESOURCES This section lists other resources, such as icons, that are used by Autopsy. @@ -140,4 +134,4 @@ WebHostingHub Glyphs - License: http://creativecommons.org/licenses/by/3.0/ Splashy Icons (free as in free) -- Web page: http://splashyfish.com/icons/ +- Web page: http://splashyfish.com/icons/ \ No newline at end of file diff --git a/test/script/tskdbdiff.py b/test/script/tskdbdiff.py index 5fcbb8ff2a..c70263fd39 100755 --- a/test/script/tskdbdiff.py +++ b/test/script/tskdbdiff.py @@ -355,6 +355,7 @@ def normalize_db_entry(line, table): object_index = line.find('INSERT INTO "tsk_objects"') report_index = line.find('INSERT INTO "reports"') layout_index = line.find('INSERT INTO "tsk_file_layout"') + data_source_info_index = line.find('INSERT INTO "data_source_info"') parens = line[line.find('(') + 1 : line.find(')')] fields_list = parens.replace(" ", "").split(',') @@ -395,6 +396,10 @@ def normalize_db_entry(line, table): fields_list[2] = "0" newLine = ('INSERT INTO "reports" VALUES(' + ','.join(fields_list) + ');') return newLine + elif (data_source_info_index != -1): + fields_list[1] = "{device id}" + newLine = ('INSERT INTO "data_source_info" VALUES(' + ','.join(fields_list) + ');') + return newLine else: return line diff --git a/thirdparty/jdiff/v-custom/doc/CHANGES.txt b/thirdparty/jdiff/v-custom/doc/CHANGES.txt index 9cff1bfdcd..a348f20369 100644 --- a/thirdparty/jdiff/v-custom/doc/CHANGES.txt +++ b/thirdparty/jdiff/v-custom/doc/CHANGES.txt @@ -25,7 +25,7 @@ task to specify the language version, e.g. for dealing with asserts. #875516 Some HTML elements in user comments were being processed incorrectly. Thanks to Jojo Dijamco for pointing this bug out. -#875470 @link tags were not exanded in user comments. +#875470 @link tags were not expanded in user comments. #877437 Other issues with @link in user comments. Many thanks to Brian Duff for these bugs and their fixes.