diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties index 0d42366b0b..ec12ed5a4d 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties @@ -220,4 +220,6 @@ XMLCaseManagement.open.msgDlg.notAutCase.msg=Error\: This is not an Autopsy conf Detail\: \n\ Cannot open a non-Autopsy config file (at {1}). XMLCaseManagement.open.msgDlg.notAutCase.title=Error -AddImageWizardIngestConfigPanel.CANCEL_BUTTON.text=Cancel \ No newline at end of file +AddImageWizardIngestConfigPanel.CANCEL_BUTTON.text=Cancel +Case.deleteReports.deleteFromDiskException.log.msg=Unable to delete the report from the disk. +Case.deleteReports.deleteFromDiskException.msg=Unable to delete the report {0} from the disk.\nYou may manually delete it from {1} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index b4c61305b2..a9f97e4a7b 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -30,6 +30,7 @@ import java.nio.file.InvalidPathException; import java.nio.file.Paths; import java.text.DateFormat; import java.text.SimpleDateFormat; +import java.util.Collection; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.HashSet; @@ -40,6 +41,7 @@ import java.util.TimeZone; import java.util.logging.Level; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; +import org.apache.commons.io.FileUtils; import org.openide.util.Lookup; import org.openide.util.NbBundle; import org.openide.util.actions.CallableSystemAction; @@ -141,17 +143,31 @@ public class Case implements SleuthkitCase.ErrorObserver { * value is a reference to a Report object representing the new report. */ REPORT_ADDED, - /** Property name for the event when a new BlackBoardArtifactTag is - * added. The new value is tag added, the old value is empty */ + /** + * Name for the property change event when a report is deleted + * from the case. Both the old value and the new value supplied by the + * event object are null. + */ + REPORT_DELETED, + /** + * Property name for the event when a new BlackBoardArtifactTag is + * added. The new value is tag added, the old value is empty + */ BLACKBOARD_ARTIFACT_TAG_ADDED, - /** Property name for the event when a new BlackBoardArtifactTag is - * deleted. The new value is empty, the old value is the deleted tag */ + /** + * Property name for the event when a new BlackBoardArtifactTag is + * deleted. The new value is empty, the old value is the deleted tag + */ BLACKBOARD_ARTIFACT_TAG_DELETED, - /** Property name for the event when a new ContentTag is - * added. The new value is tag added, the old value is empty */ + /** + * Property name for the event when a new ContentTag is added. The new + * value is tag added, the old value is empty + */ CONTENT_TAG_ADDED, - /** Property name for the event when a new ContentTag is - * deleted. The new value is empty, the old value is the deleted tag */ + /** + * Property name for the event when a new ContentTag is deleted. The new + * value is empty, the old value is the deleted tag + */ CONTENT_TAG_DELETED; }; @@ -1257,6 +1273,49 @@ public class Case implements SleuthkitCase.ErrorObserver { return this.db.getAllReports(); } + /** + * Deletes reports from the case - deletes it from the disk as well as the + * database. + * + * @param reports Collection of Report to be deleted from the case. + * @param deleteFromDisk Set true to perform reports file deletion from + * disk. + * @throws TskCoreException + */ + public void deleteReports(Collection reports, boolean deleteFromDisk) throws TskCoreException { + + String pathToReportsFolder = Paths.get(this.db.getDbDirPath(), "Reports").normalize().toString(); // NON-NLS + for (Report report : reports) { + + // delete from the database. + this.db.deleteReport(report); + + if (deleteFromDisk) { + // traverse to the root directory of Report report. + String reportPath = report.getPath(); + while (!Paths.get(reportPath, "..").normalize().toString().equals(pathToReportsFolder)) { // NON-NLS + reportPath = Paths.get(reportPath, "..").normalize().toString(); // NON-NLS + } + + // delete from the disk. + try { + FileUtils.deleteDirectory(new File(reportPath)); + } catch (IOException | SecurityException ex) { + logger.log(Level.WARNING, NbBundle.getMessage(Case.class, "Case.deleteReports.deleteFromDiskException.log.msg"), ex); + JOptionPane.showMessageDialog(null, NbBundle.getMessage(Case.class, "Case.deleteReports.deleteFromDiskException.msg", report.getReportName(), reportPath)); + } + } + + // fire property change event. + try { + Case.pcs.firePropertyChange(Events.REPORT_DELETED.toString(), null, null); + } catch (Exception ex) { + String errorMessage = String.format("A Case %s listener threw an exception", Events.REPORT_DELETED.toString()); //NON-NLS + logger.log(Level.SEVERE, errorMessage, ex); + } + } + } + /** * Returns if the case has data in it yet. * diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseCloseAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseCloseAction.java index 900a355bf0..29dfdeda09 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseCloseAction.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseCloseAction.java @@ -23,24 +23,9 @@ import java.awt.Component; import java.awt.EventQueue; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.util.logging.Level;import org.sleuthkit.autopsy.coreutils.Logger; -import javax.swing.Action; -import javax.swing.ImageIcon; -import javax.swing.JButton; -import org.openide.util.HelpCtx; -import org.openide.util.NbBundle; -import org.openide.util.actions.CallableSystemAction; -import org.openide.util.actions.Presenter; -; -import org.sleuthkit.autopsy.coreutils.Logger; -import javax.swing.Action; -import javax.swing.ImageIcon; -import javax.swing.JButton; -import org.openide.util.HelpCtx; -import org.openide.util.NbBundle; -import org.openide.util.actions.CallableSystemAction; -import org.openide.util.actions.Presenter; +import java.util.logging.Level; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import javax.swing.Action; import javax.swing.ImageIcon; import javax.swing.JButton; @@ -87,6 +72,10 @@ import org.openide.util.actions.Presenter; return; Case result = Case.getCurrentCase(); + + if(!MessageNotifyUtil.Message.confirm("Are you sure you want to close current case?")) + return; + try { result.closeCase(); EventQueue.invokeLater(new Runnable() { diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle_ja.properties old mode 100644 new mode 100755 diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java index 3bbc35b0fa..3013703d24 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2014 Basis Technology Corp. + * Copyright 2011-2015 Basis Technology Corp. * Contact: carrier sleuthkit org *s * Licensed under the Apache License, Version 2.0 (the "License"); @@ -54,12 +54,10 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo //UI private final MediaViewVideoPanel videoPanel; private final SortedSet videoExtensions; // get them from the panel - private final SortedSet imageExtensions; private final SortedSet videoMimes; - private final SortedSet imageMimes; private final MediaViewImagePanel imagePanel; - private boolean videoPanelInited; - private boolean imagePanelInited; + private final boolean videoPanelInited; + private final boolean imagePanelInited; private static final String IMAGE_VIEWER_LAYER = "IMAGE"; //NON-NLS private static final String VIDEO_VIEWER_LAYER = "VIDEO"; //NON-NLS @@ -78,8 +76,6 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo imagePanel = new MediaViewImagePanel(); imagePanelInited = imagePanel.isInited(); - imageMimes = new TreeSet<>(imagePanel.getMimeTypes()); - imageExtensions = new TreeSet<>(imagePanel.getExtensions()); customizeComponents(); logger.log(Level.INFO, "Created MediaView instance: " + this); //NON-NLS @@ -195,9 +191,9 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo //TODO: is this what we want, to require both extension and mimetype support? if (AUDIO_EXTENSIONS.contains("." + extension) || videoExtensions.contains("." + extension)) { try { - String mimeType = new FileTypeDetector().detect(file); - if (nonNull(mimeType) && videoMimes.contains(mimeType)) { - return true; + String mimeType = new FileTypeDetector().getFileType(file); + if (nonNull(mimeType)) { + return videoMimes.contains(mimeType); } } catch (FileTypeDetector.FileTypeDetectorInitException | TskCoreException ex) { logger.log(Level.WARNING, "Failed to look up mimetype for " + file.getName() + " using FileTypeDetector. Fallingback on AbstractFile.isMimeType", ex); @@ -206,6 +202,7 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo } } } + return false; } @@ -217,36 +214,8 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo * @return True if an image file that can be displayed */ private boolean isImageSupported(AbstractFile file) { - String extension = file.getNameExtension(); - // blackboard - try { - String mimeType = new FileTypeDetector().detect(file); - if (nonNull(mimeType) && imageMimes.contains(mimeType)) { - return true; - } - } catch (FileTypeDetector.FileTypeDetectorInitException | TskCoreException ex) { - logger.log(Level.WARNING, "Failed to look up mimetype for " + file.getName() + " using FileTypeDetector. Fallingback on AbstractFile.isMimeType", ex); - if (!imageMimes.isEmpty()) { - MimeMatchEnum mimeMatch = file.isMimeType(imageMimes); - if (mimeMatch == MimeMatchEnum.TRUE) { - return true; - } else if (mimeMatch == MimeMatchEnum.FALSE) { - return false; - } - } - } - - // extension - if (imageExtensions.contains("." + extension)) { - return true; - } - - // our own signature checks for important types - if (ImageUtils.isJpegFileHeader(file)) { - return true; - } - return ImageUtils.isPngFileHeader(file); + return ImageUtils.thumbnailSupported(file); } @Override @@ -264,19 +233,11 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo return false; } - if (imagePanelInited) { - if (isImageSupported(file)) { - return true; - } + if (imagePanelInited && isImageSupported(file)) { + return true; } - if (videoPanelInited && videoPanel.isInited()) { - if (isVideoSupported(file)) { - return true; - } - } - - return false; + return videoPanelInited && isVideoSupported(file); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java index 88d8706e71..9ba152525c 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java @@ -65,7 +65,7 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C private DataContent customContentViewer; private boolean isMain; private String title; - private final DummyNodeListener dummyNodeListener = new DummyNodeListener(); + private final RootNodeListener rootNodeListener = new RootNodeListener(); private static final Logger logger = Logger.getLogger(DataResultPanel.class.getName() ); private boolean listeningToTabbedPane = false; @@ -369,7 +369,7 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C @Override public void setNode(Node selectedNode) { if (this.rootNode != null) { - this.rootNode.removeNodeListener(dummyNodeListener); + this.rootNode.removeNodeListener(rootNodeListener); } // Deferring becoming a listener to the tabbed pane until this point // eliminates handling a superfluous stateChanged event during construction. @@ -380,8 +380,8 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C this.rootNode = selectedNode; if (this.rootNode != null) { - dummyNodeListener.reset(); - this.rootNode.addNodeListener(dummyNodeListener); + rootNodeListener.reset(); + this.rootNode.addNodeListener(rootNodeListener); } resetTabs(selectedNode); @@ -620,28 +620,33 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C } } - private class DummyNodeListener implements NodeListener { + private class RootNodeListener implements NodeListener { + + private volatile boolean waitingForData = true; - private volatile boolean load = true; - public void reset() { - load = true; + waitingForData = true; } - + @Override public void childrenAdded(final NodeMemberEvent nme) { Node[] delta = nme.getDelta(); - if (load && containsReal(delta)) { - load = false; + updateMatches(); + + /* There is a known issue in this code whereby we will only + call setupTabs() once even though childrenAdded could be + called multiple times. That means that each panel may not + have access to all of the children when they decide if they + support the content */ + if (waitingForData && containsReal(delta)) { + waitingForData = false; if (SwingUtilities.isEventDispatchThread()) { setupTabs(nme.getNode()); - updateMatches(); } else { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { setupTabs(nme.getNode()); - updateMatches(); } }); } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewImagePanel.css b/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewImagePanel.css new file mode 100644 index 0000000000..8cd592b28b --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewImagePanel.css @@ -0,0 +1,28 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2015 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. + */ + +.label { + -fx-wrap-text:true; + -fx-text-fill: red; + -fx-font-size: 2em; +} + +.bg { + -fx-background-color:black; +} \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewImagePanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewImagePanel.java index 584e5babb5..c1a80e5566 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewImagePanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/MediaViewImagePanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013 Basis Technology Corp. + * Copyright 2013-15 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,41 +21,65 @@ package org.sleuthkit.autopsy.corecomponents; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.image.BufferedImage; +import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; -import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collections; import java.util.List; +import java.util.SortedSet; import java.util.logging.Level; +import java.util.stream.Collectors; import javafx.application.Platform; import javafx.embed.swing.JFXPanel; import javafx.embed.swing.SwingFXUtils; import javafx.scene.Scene; +import javafx.scene.control.Label; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.BorderPane; import javax.imageio.ImageIO; +import javax.swing.JPanel; import javax.swing.SwingUtilities; import org.openide.util.NbBundle; +import org.python.google.common.collect.Lists; import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.corelibs.ScalrWrapper; +import org.sleuthkit.autopsy.coreutils.ImageUtils; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.ReadContentInputStream; /** - * Container for the image viewer part of media view, on a layered pane. To be - * used with JavaFx image viewer only. + * Image viewer part of the Media View layered pane. Uses JavaFX to display the + * image. */ - public class MediaViewImagePanel extends javax.swing.JPanel { +public class MediaViewImagePanel extends JPanel { + + private static final Logger LOGGER = Logger.getLogger(MediaViewImagePanel.class.getName()); + + private final boolean fxInited; + private JFXPanel fxPanel; private ImageView fxImageView; - private static final Logger logger = Logger.getLogger(MediaViewImagePanel.class.getName()); - private boolean fxInited = false; - - private final List supportedExtensions; - static private final List supportedMimes = Arrays.asList("image/jpeg", "image/png", "image/gif", "image/bmp", "image/x-ms-bmp"); //NON-NLS + private BorderPane borderpane; + + private final Label errorLabel = new Label("Could not load image file into media view."); + private final Label tooLargeLabel = new Label("Could not load image file into media view (too large)."); + private final Label noReaderLabel = new Label("Image reader not found for file."); + + /** + * mime types we should be able to display. if the mimetype is unknown we + * will fall back on extension and jpg/png header + */ + static private final SortedSet supportedMimes = ImageUtils.getSupportedMimeTypes(); + + /** + * extensions we should be able to display + */ + static private final List supportedExtensions = ImageUtils.getSupportedExtensions().stream() + .map("."::concat) + .collect(Collectors.toList()); /** * Creates new form MediaViewImagePanel @@ -64,74 +88,59 @@ import org.sleuthkit.datamodel.ReadContentInputStream; initComponents(); fxInited = org.sleuthkit.autopsy.core.Installer.isJavaFxInited(); if (fxInited) { - setupFx(); - } - - supportedExtensions = new ArrayList<>(); - //logger.log(Level.INFO, "Supported image formats by javafx image viewer: "); - for (String suffix : ImageIO.getReaderFileSuffixes()) { - //logger.log(Level.INFO, "suffix: " + suffix); - supportedExtensions.add("." + suffix); + Platform.runLater(() -> { + + // build jfx ui (we could do this in FXML?) + fxImageView = new ImageView(); // will hold image + borderpane = new BorderPane(fxImageView); // centers and sizes imageview + borderpane.getStyleClass().add("bg"); + fxPanel = new JFXPanel(); // bridge jfx-swing + Scene scene = new Scene(borderpane); //root of jfx tree + scene.getStylesheets().add(MediaViewImagePanel.class.getResource("MediaViewImagePanel.css").toExternalForm()); + fxPanel.setScene(scene); + + //bind size of image to that of scene, while keeping proportions + fxImageView.fitWidthProperty().bind(scene.widthProperty()); + fxImageView.fitHeightProperty().bind(scene.heightProperty()); + fxImageView.setPreserveRatio(true); + fxImageView.setSmooth(true); + fxImageView.setCache(true); + + EventQueue.invokeLater(() -> { + add(fxPanel);//add jfx ui to JPanel + }); + }); } } - + public boolean isInited() { return fxInited; } /** - * Setup FX components + * clear the displayed image */ - private void setupFx() { - // load the image - Platform.runLater(new Runnable() { - @Override - public void run() { - fxPanel = new JFXPanel(); - fxImageView = new ImageView(); - // resizes the image to have width of 100 while preserving the ratio and using - // higher quality filtering method; this ImageView is also cached to - // improve performance - fxImageView.setPreserveRatio(true); - fxImageView.setSmooth(true); - fxImageView.setCache(true); - - EventQueue.invokeLater(new Runnable() { - @Override - public void run() { - add(fxPanel); - - //TODO - // setVisible(true); - } - }); - } - }); - } - public void reset() { - Platform.runLater(new Runnable() { - @Override - public void run() { - fxImageView.setImage(null); - } + Platform.runLater(() -> { + fxImageView.setImage(null); + borderpane.setCenter(null); }); } - + /** - * Show image + * Show the contents of the given AbstractFile as a visual image. * * @param file image file to show - * @param dims dimension of the parent window + * @param dims dimension of the parent window (ignored) */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) void showImageFx(final AbstractFile file, final Dimension dims) { if (!fxInited) { return; } - final String fileName = file.getName(); - //hide the panel during loading/transformations + //TODO: repalce this with a progress indicator fxPanel.setVisible(false); // load the image @@ -139,90 +148,60 @@ import org.sleuthkit.datamodel.ReadContentInputStream; @Override public void run() { if (!Case.isCaseOpen()) { - //handle in-between condition when case is being closed - //and an image was previously selected + /* handle in-between condition when case is being closed + * and an image was previously selected */ return; } + try (InputStream inputStream = new BufferedInputStream(new ReadContentInputStream(file));) { - final InputStream inputStream = new ReadContentInputStream(file); - - final Image fxImage; - try { - //original input stream - BufferedImage bi = ImageIO.read(inputStream); - if (bi == null) { - logger.log(Level.WARNING, "Could image reader not found for file: " + fileName); //NON-NLS - return; + BufferedImage bufferedImage = ImageIO.read(inputStream); + if (bufferedImage == null) { + LOGGER.log(Level.WARNING, "Image reader not found for file: {0}", file.getName()); //NON-NLS + borderpane.setCenter(noReaderLabel); + } else { + Image fxImage = SwingFXUtils.toFXImage(bufferedImage, null); + if (fxImage.isError()) { + LOGGER.log(Level.WARNING, "Could not load image file into media view: " + file.getName(), fxImage.getException()); //NON-NLS + borderpane.setCenter(errorLabel); + return; + } else { + fxImageView.setImage(fxImage); + borderpane.setCenter(fxImageView); + } } - //scale image using Scalr - BufferedImage biScaled = ScalrWrapper.resizeHighQuality(bi, (int) dims.getWidth(), (int) dims.getHeight()); - //convert from awt imageto fx image - fxImage = SwingFXUtils.toFXImage(biScaled, null); - } catch (IOException ex) { - logger.log(Level.WARNING, "Could not load image file into media view: " + fileName, ex); //NON-NLS - return; - } catch (OutOfMemoryError ex) { - logger.log(Level.WARNING, "Could not load image file into media view (too large): " + fileName, ex); //NON-NLS + } catch (IllegalArgumentException | IOException ex) { + LOGGER.log(Level.WARNING, "Could not load image file into media view: " + file.getName(), ex); //NON-NLS + borderpane.setCenter(errorLabel); + } catch (OutOfMemoryError ex) { // this might be redundant since we are not attempting to rescale the image anymore + LOGGER.log(Level.WARNING, "Could not load image file into media view (too large): " + file.getName(), ex); //NON-NLS MessageNotifyUtil.Notify.warn( NbBundle.getMessage(this.getClass(), "MediaViewImagePanel.imgFileTooLarge.msg", file.getName()), ex.getMessage()); - return; - } finally { - try { - inputStream.close(); - } catch (IOException ex) { - logger.log(Level.WARNING, "Could not close input stream after loading image in media view: " + fileName, ex); //NON-NLS - } + borderpane.setCenter(tooLargeLabel); } - if (fxImage == null || fxImage.isError()) { - logger.log(Level.WARNING, "Could not load image file into media view: " + fileName); //NON-NLS - return; - } - - //use border pane to center the image in the scene - BorderPane borderpane = new BorderPane(); - borderpane.setCenter(fxImageView); - - fxImageView.setImage(fxImage); - fxImageView.setFitWidth(dims.getWidth()); - fxImageView.setFitHeight(dims.getHeight()); - - //Group fxRoot = new Group(); - - //Scene fxScene = new Scene(fxRoot, dims.getWidth(), dims.getHeight(), javafx.scene.paint.Color.BLACK); - Scene fxScene = new Scene(borderpane, javafx.scene.paint.Color.BLACK); - // borderpane.getChildren().add(fxImageView); - - fxPanel.setScene(fxScene); - - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - //show the panel after fully loaded - fxPanel.setVisible(true); - } + SwingUtilities.invokeLater(() -> { + //show the panel after fully loaded + fxPanel.setVisible(true); }); - } }); - } - + /** - * returns supported mime types - * @return + * @return supported mime types */ public List getMimeTypes() { - return supportedMimes; + return Collections.unmodifiableList(Lists.newArrayList(supportedMimes)); } - + /** * returns supported extensions (each starting with .) - * @return + * + * @return */ public List getExtensions() { - return supportedExtensions; + return Collections.unmodifiableList(supportedExtensions); } /** @@ -239,4 +218,4 @@ import org.sleuthkit.datamodel.ReadContentInputStream; }// //GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables // End of variables declaration//GEN-END:variables -} \ No newline at end of file +} diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewChildren.java b/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewChildren.java index fdd35fc983..65c97fb4c2 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewChildren.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewChildren.java @@ -43,7 +43,7 @@ class ThumbnailViewChildren extends Children.Keys { static final int IMAGES_PER_PAGE = 200; private Node parent; - private final HashMap> pages = new HashMap>(); + private final HashMap> pages = new HashMap<>(); private int totalImages = 0; private int totalPages = 0; private int iconSize = ImageUtils.ICON_SIZE_MEDIUM; @@ -85,7 +85,7 @@ class ThumbnailViewChildren extends Children.Keys { //TODO when lazy loading of original nodes is fixed //we should be asking the datamodel for the children instead //and not counting the children nodes (which might not be preloaded at this point) - final List suppContent = new ArrayList(); + final List suppContent = new ArrayList<>(); for (Node child : parent.getChildren().getNodes()) { if (isSupported(child)) { ++totalImages; diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewNode.java b/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewNode.java index 8d05282b68..de26a7977f 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewNode.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewNode.java @@ -77,7 +77,7 @@ class ThumbnailViewNode extends FilterNode { } else { final Content content = this.getLookup().lookup(Content.class); if (content == null) { - return ImageUtils.getDefaultIcon(); + return ImageUtils.getDefaultThumbnail(); } if (swingWorker == null || swingWorker.isDone()) { swingWorker = new SwingWorker() { @@ -86,7 +86,7 @@ class ThumbnailViewNode extends FilterNode { @Override protected Image doInBackground() throws Exception { progressHandle.start(); - return ImageUtils.getIcon(content, iconSize); + return ImageUtils.getThumbnail(content, iconSize); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java b/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java index 43ccdcdf43..5b631ffb01 100755 --- a/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java @@ -2,7 +2,7 @@ * * Autopsy Forensic Browser * - * Copyright 2012 Basis Technology Corp. + * Copyright 2012-15 Basis Technology Corp. * * Copyright 2012 42six Solutions. * Contact: aebadirad 42six com @@ -25,42 +25,59 @@ package org.sleuthkit.autopsy.coreutils; import com.google.common.io.Files; import java.awt.Image; import java.awt.image.BufferedImage; +import java.io.BufferedInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; +import java.util.Objects; +import static java.util.Objects.isNull; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; import java.util.logging.Level; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import javax.imageio.ImageIO; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.concurrent.BasicThreadFactory; import org.netbeans.api.progress.ProgressHandle; import org.netbeans.api.progress.ProgressHandleFactory; import org.opencv.core.Core; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.corelibs.ScalrWrapper; import org.sleuthkit.autopsy.datamodel.ContentUtils; +import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; +import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector.FileTypeDetectorInitException; import org.sleuthkit.datamodel.AbstractFile; -import org.sleuthkit.datamodel.BlackboardAttribute; -import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.ReadContentInputStream; import org.sleuthkit.datamodel.TskCoreException; /** - * Utilities for creating and manipulating thumbnail and icon images. * + * Utilities for working with Images and creating thumbnails. Reuses thumbnails + * by storing them in the case's cache directory. */ public class ImageUtils { private static final Logger LOGGER = Logger.getLogger(ImageUtils.class.getName()); + /** save thumbnails to disk as this format */ + private static final String FORMAT = "png"; //NON-NLS + public static final int ICON_SIZE_SMALL = 50; public static final int ICON_SIZE_MEDIUM = 100; public static final int ICON_SIZE_LARGE = 200; private static final Logger logger = LOGGER; private static final BufferedImage DEFAULT_ICON; + private static final Image DEFAULT_THUMBNAIL; private static final List SUPP_IMAGE_EXTENSIONS = new ArrayList<>(Arrays.asList(ImageIO.getReaderFileSuffixes())); //final private static final List SUPP_IMAGE_MIME_TYPES = new ArrayList<>(Arrays.asList(ImageIO.getReaderMIMETypes())); // final private static final List SUPP_VIDEO_EXTENSIONS @@ -118,9 +135,77 @@ public class ImageUtils { * Get the default Icon, which is the icon for a file. * * @return + * + * + * + * /** initialized lazily */ + private static FileTypeDetector fileTypeDetector; + + private static final List SUPPORTED_EXTENSIONS; + private static final TreeSet SUPPORTED_MIME_TYPES; + + /** thread that saves generated thumbnails to disk in the background */ + private static final Executor imageSaver + = Executors.newSingleThreadExecutor(new BasicThreadFactory.Builder() + .namingPattern("icon saver-%d").build()); + + static { + ImageIO.scanForPlugins(); + BufferedImage defaultIcon = null; + try { + defaultIcon = ImageIO.read(ImageUtils.class.getResourceAsStream("/org/sleuthkit/autopsy/images/file-icon.png"));//NON-NLS + } catch (IOException ex) { + LOGGER.log(Level.WARNING, "Failed to read default thumbnail."); + } + DEFAULT_THUMBNAIL = defaultIcon; + + SUPPORTED_EXTENSIONS = Arrays.asList(ImageIO.getReaderFileSuffixes()); + SUPPORTED_MIME_TYPES = new TreeSet<>(Arrays.asList(ImageIO.getReaderMIMETypes())); + + /* special cases and variants that we support, but don't get registered + * with ImageIO automatically */ + SUPPORTED_MIME_TYPES.addAll(Arrays.asList( + "image/x-rgb", + "image/x-ms-bmp", + "application/x-123")); + + //this is rarely usefull + SUPPORTED_MIME_TYPES.removeIf("application/octet-stream"::equals); + } + + private ImageUtils() { + } + + public static List getSupportedExtensions() { + return Collections.unmodifiableList(SUPPORTED_EXTENSIONS); + } + + public static SortedSet getSupportedMimeTypes() { + return Collections.unmodifiableSortedSet(SUPPORTED_MIME_TYPES); + } + + /** + * Get the default thumbnail, which is the icon for a file. Used when we can + * not + * generate content based thumbnail. + * + * @return + * + * @deprecated use {@link #getDefaultThumbnail() } instead. */ + @Deprecated public static Image getDefaultIcon() { - return DEFAULT_ICON; + return getDefaultThumbnail(); + } + + /** + * Get the default thumbnail, which is the icon for a file. Used when we can + * not generate content based thumbnail. + * + * @return the default thumbnail + */ + public static Image getDefaultThumbnail() { + return DEFAULT_THUMBNAIL; } /** @@ -129,45 +214,61 @@ public class ImageUtils { * @param content * * @return + * */ public static boolean thumbnailSupported(Content content) { - if (content instanceof AbstractFile == false) { - return false; - } - AbstractFile f = (AbstractFile) content; - if (f.getSize() == 0) { - return false; - } - // check the blackboard for a file type attribute + if (content.getSize() == 0) { + return false; + } + if (!(content instanceof AbstractFile)) { + return false; + } + AbstractFile file = (AbstractFile) content; + try { - //TODO: Use FileTypeDetector here? - ArrayList attributes = f.getGenInfoAttributes(ATTRIBUTE_TYPE.TSK_FILE_TYPE_SIG); - for (BlackboardAttribute attribute : attributes) { - if (SUPP_IMAGE_MIME_TYPES.contains(attribute.getValueString()) || SUPP_VIDEO_MIME_TYPES.contains(attribute.getValueString())) { + + String mimeType = getFileTypeDetector().getFileType(file); + if (Objects.nonNull(mimeType)) { + return SUPPORTED_MIME_TYPES.contains(mimeType) + || (mimeType.equalsIgnoreCase("audio/x-aiff") && "iff".equalsIgnoreCase(file.getNameExtension())); + } + } catch (FileTypeDetector.FileTypeDetectorInitException | TskCoreException ex) { + LOGGER.log(Level.WARNING, "Failed to look up mimetype for " + file.getName() + " using FileTypeDetector. Fallingback on AbstractFile.isMimeType", ex); + if (!SUPPORTED_MIME_TYPES.isEmpty()) { + AbstractFile.MimeMatchEnum mimeMatch = file.isMimeType(SUPPORTED_MIME_TYPES); + if (mimeMatch == AbstractFile.MimeMatchEnum.TRUE) { + return true; + } else if (mimeMatch == AbstractFile.MimeMatchEnum.FALSE) { + return false; } } - - // if the file type is known and we don't support it, bail - if (attributes.size() > 0) { - return false; - } - } catch (TskCoreException ex) { - logger.log(Level.WARNING, "Error while getting file signature from blackboard.", ex); //NON-NLS } // if we have an extension, check it - final String extension = f.getNameExtension(); - if (extension.isEmpty() == false) { - // Note: thumbnail generator only supports JPG, GIF, and PNG for now - if (SUPP_IMAGE_EXTENSIONS.contains(extension) || SUPP_VIDEO_EXTENSIONS.contains(extension)) { - return true; - } + final String extension = file.getNameExtension(); + if (StringUtils.isNotBlank(extension) && SUPPORTED_EXTENSIONS.contains(extension)) { + return true; } // if no extension or one that is not for an image, then read the content - return isJpegFileHeader(f) || isPngFileHeader(f); + return isJpegFileHeader(file) || isPngFileHeader(file); + } + + /** + * returns a lazily instatiated FileTypeDetector + * + * @return a FileTypeDetector + * + * @throws FileTypeDetectorInitException if a initializing the + * FileTypeDetector failed. + */ + synchronized private static FileTypeDetector getFileTypeDetector() throws FileTypeDetector.FileTypeDetectorInitException { + if (fileTypeDetector == null) { + fileTypeDetector = new FileTypeDetector(); + } + return fileTypeDetector; } /** @@ -177,42 +278,48 @@ public class ImageUtils { * @param content * @param iconSize * - * @return + * + * @return a thumbnail for the given image or a default one if there was a + * problem making a thumbnail. + * + * @deprecated use {@link #getThumbnail(org.sleuthkit.datamodel.Content, int) + * } instead. + * */ + @Nonnull + @Deprecated public static Image getIcon(Content content, int iconSize) { - //TODO: why do we allow Content here if we only handle AbstractFiles? + return getThumbnail(content, iconSize); + } - Image icon = null; + /** + * Get a thumbnail of a specified size. Generates the image if it is + * not already cached. + * + * @param content + * @param iconSize + * + * @return a thumbnail for the given image or a default one if there was a + * problem making a thumbnail. + */ + public static Image getThumbnail(Content content, int iconSize) { // If a thumbnail file is already saved locally - // @@@ Bug here in that we do not refer to size in the cache. - - File iconFile = getCachedThumbnailLocation(content.getId()); - // If a thumbnail file is already saved locally - if (iconFile.exists()) { + File cacheFile = getCachedThumbnailLocation(content.getId()); + if (cacheFile.exists()) { try { - BufferedImage bicon = ImageIO.read(iconFile); - if (bicon == null) { - icon = DEFAULT_ICON; - } else if (bicon.getWidth() != iconSize) { - icon = generateAndSaveIcon(content, iconSize, iconFile); + BufferedImage thumbnail = ImageIO.read(cacheFile); + if (isNull(thumbnail) || thumbnail.getWidth() != iconSize) { + return generateAndSaveThumbnail(content, iconSize, cacheFile); } else { - icon = bicon; + return thumbnail; } - } catch (Exception ex) { - logger.log(Level.WARNING, "Error while reading image.", ex); //NON-NLS - icon = DEFAULT_ICON; + } catch (IOException ex) { + LOGGER.log(Level.WARNING, "Error while reading image.", ex); //NON-NLS + return generateAndSaveThumbnail(content, iconSize, cacheFile); } } else { - final String extension = ((AbstractFile) content).getNameExtension(); - - if (SUPP_VIDEO_EXTENSIONS.contains(extension) || SUPP_IMAGE_EXTENSIONS.contains(extension)) { - icon = generateAndSaveIcon(content, iconSize, iconFile); - } + return generateAndSaveThumbnail(content, iconSize, cacheFile); } - if (icon == null) { - return DEFAULT_ICON; - } - return icon; } /** @@ -222,13 +329,35 @@ public class ImageUtils { * @param content * @param iconSize * - * @return File object for cached image. Is guaranteed to exist. + * @return File object for cached image. Is guaranteed to exist, as long as + * there was not an error generating or saving the thumbnail. + * + * @deprecated use {@link #getCachedThumbnailFile(org.sleuthkit.datamodel.Content, int) + * } instead. + * */ + @Nullable + @Deprecated public static File getIconFile(Content content, int iconSize) { - if (getIcon(content, iconSize) != null) { - return getFile(content.getId()); - } - return null; + return getCachedThumbnailFile(content, iconSize); + + } + + /** + * + * Get a thumbnail of a specified size. Generates the image if it is + * not already cached. + * + * @param content + * @param iconSize + * + * @return File object for cached image. Is guaranteed to exist, as long as + * there was not an error generating or saving the thumbnail. + */ + @Nullable + public static File getCachedThumbnailFile(Content content, int iconSize) { + getThumbnail(content, iconSize); + return getCachedThumbnailLocation(content.getId()); } /** @@ -239,7 +368,11 @@ public class ImageUtils { * * @return * + * + * @deprecated this should never have been public. */ + @Deprecated + public static File getFile(long id) { return getCachedThumbnailLocation(id); } @@ -258,7 +391,7 @@ public class ImageUtils { } /** - * Check if is jpeg file based on header + * Check if the given file is a jpeg based on header. * * @param file * @@ -269,125 +402,137 @@ public class ImageUtils { return false; } - byte[] fileHeaderBuffer = new byte[2]; - int bytesRead; try { - bytesRead = file.read(fileHeaderBuffer, 0, 2); + byte[] fileHeaderBuffer = readHeader(file, 2); + /* Check for the JPEG header. Since Java bytes are signed, we cast + * them to an int first. */ + return (((fileHeaderBuffer[0] & 0xff) == 0xff) && ((fileHeaderBuffer[1] & 0xff) == 0xd8)); } catch (TskCoreException ex) { //ignore if can't read the first few bytes, not a JPEG return false; } - if (bytesRead != 2) { - return false; - } - /* - * Check for the JPEG header. Since Java bytes are signed, we cast them - * to an int first. - */ - return (((fileHeaderBuffer[0] & 0xff) == 0xff) && ((fileHeaderBuffer[1] & 0xff) == 0xd8)); } + /** + * Check if the given file is a png based on header. + * + * @param file + * + * @return true if png file, false otherwise + */ public static boolean isPngFileHeader(AbstractFile file) { if (file.getSize() < 10) { return false; } - byte[] fileHeaderBuffer = new byte[8]; - int bytesRead; try { - bytesRead = file.read(fileHeaderBuffer, 0, 8); + byte[] fileHeaderBuffer = readHeader(file, 8); + /* Check for the png header. Since Java bytes are signed, we cast + * them to an int first. */ + return (((fileHeaderBuffer[1] & 0xff) == 0x50) && ((fileHeaderBuffer[2] & 0xff) == 0x4E) + && ((fileHeaderBuffer[3] & 0xff) == 0x47) && ((fileHeaderBuffer[4] & 0xff) == 0x0D) + && ((fileHeaderBuffer[5] & 0xff) == 0x0A) && ((fileHeaderBuffer[6] & 0xff) == 0x1A) + && ((fileHeaderBuffer[7] & 0xff) == 0x0A)); + } catch (TskCoreException ex) { + //ignore if can't read the first few bytes, not an png + return false; + } + } + + private static byte[] readHeader(AbstractFile file, int buffLength) throws TskCoreException { + byte[] fileHeaderBuffer = new byte[buffLength]; + int bytesRead = file.read(fileHeaderBuffer, 0, buffLength); + + if (bytesRead != buffLength) { //ignore if can't read the first few bytes, not an image - return false; + throw new TskCoreException("Could not read " + buffLength + " bytes from " + file.getName()); } - if (bytesRead != 8) { - return false; - } - /* - * Check for the header. Since Java bytes are signed, we cast them - * to an int first. - */ - return (((fileHeaderBuffer[1] & 0xff) == 0x50) && ((fileHeaderBuffer[2] & 0xff) == 0x4E) - && ((fileHeaderBuffer[3] & 0xff) == 0x47) && ((fileHeaderBuffer[4] & 0xff) == 0x0D) - && ((fileHeaderBuffer[5] & 0xff) == 0x0A) && ((fileHeaderBuffer[6] & 0xff) == 0x1A) - && ((fileHeaderBuffer[7] & 0xff) == 0x0A)); + return fileHeaderBuffer; } /** * Generate an icon and save it to specified location. * - * @param content File to generate icon for + * @param content File to generate icon for * @param iconSize - * @param saveFile Location to save thumbnail to + * @param cacheFile Location to save thumbnail to * * @return Generated icon or null on error */ - private static Image generateAndSaveIcon(Content content, int iconSize, File saveFile) { + private static Image generateAndSaveThumbnail(Content content, int iconSize, File cacheFile) { AbstractFile f = (AbstractFile) content; final String extension = f.getNameExtension(); - BufferedImage icon = null; + BufferedImage thumbnail = null; try { if (SUPP_VIDEO_EXTENSIONS.contains(extension)) { if (openCVLoaded) { - icon = VideoUtils.generateVideoThumbnail((AbstractFile) content, iconSize); + thumbnail = VideoUtils.generateVideoThumbnail((AbstractFile) content, iconSize); } else { return DEFAULT_ICON; } } else if (SUPP_IMAGE_EXTENSIONS.contains(extension)) { - icon = generateImageThumbnail(content, iconSize); + thumbnail = generateImageThumbnail(content, iconSize); } - if (icon == null) { + if (thumbnail == null) { return DEFAULT_ICON; } else { - if (saveFile.exists()) { - saveFile.delete(); - } - Files.createParentDirs(saveFile); - ImageIO.write(icon, "png", saveFile); //NON-NLS + BufferedImage toSave = thumbnail; + imageSaver.execute(() -> { + try { + Files.createParentDirs(cacheFile); + if (cacheFile.exists()) { + cacheFile.delete(); + } + ImageIO.write(toSave, FORMAT, cacheFile); + } catch (IllegalArgumentException | IOException ex1) { + LOGGER.log(Level.WARNING, "Could not write cache thumbnail: " + content, ex1); //NON-NLS + } + }); } - } catch (NullPointerException | IOException ex) { + } catch (NullPointerException ex) { logger.log(Level.WARNING, "Could not write cache thumbnail: " + content, ex); //NON-NLS } - return icon; + return thumbnail; } - /* + /** + * * Generate and return a scaled image + * + * @param content + * @param iconSize + * + * @return a Thumbnail of the given content at the given size, or null if + * there was a problem. */ + @Nullable private static BufferedImage generateImageThumbnail(Content content, int iconSize) { - InputStream inputStream = null; - BufferedImage bi = null; - try { - inputStream = new ReadContentInputStream(content); - bi = ImageIO.read(inputStream); + try (InputStream inputStream = new BufferedInputStream(new ReadContentInputStream(content));) { + BufferedImage bi = ImageIO.read(inputStream); + if (bi == null) { - logger.log(Level.WARNING, "No image reader for file: " + content.getName()); //NON-NLS + LOGGER.log(Level.WARNING, "No image reader for file: {0}", content.getName()); //NON-NLS return null; } - return ScalrWrapper.resizeFast(bi, iconSize); - - } catch (IllegalArgumentException e) { - // if resizing does not work due to extremely small height/width ratio, - // crop the image instead. - BufferedImage biCropped = ScalrWrapper.cropImage(bi, Math.min(iconSize, bi.getWidth()), Math.min(iconSize, bi.getHeight())); - return biCropped; + try { + return ScalrWrapper.resizeFast(bi, iconSize); + } catch (IllegalArgumentException e) { + // if resizing does not work due to extreme aspect ratio, + // crop the image instead. + return ScalrWrapper.cropImage(bi, Math.min(iconSize, bi.getWidth()), Math.min(iconSize, bi.getHeight())); + } } catch (OutOfMemoryError e) { - logger.log(Level.WARNING, "Could not scale image (too large): " + content.getName(), e); //NON-NLS + LOGGER.log(Level.WARNING, "Could not scale image (too large): " + content.getName(), e); //NON-NLS + return null; } catch (Exception e) { - logger.log(Level.WARNING, "Could not scale image: " + content.getName(), e); //NON-NLS + LOGGER.log(Level.WARNING, "Could not scale image: " + content.getName(), e); //NON-NLS return null; - } finally { - if (inputStream != null) { - try { - inputStream.close(); - } catch (IOException ex) { - logger.log(Level.WARNING, "Could not close input stream after resizing thumbnail: " + content.getName(), ex); //NON-NLS - } - } + } } @@ -411,7 +556,4 @@ public class ImageUtils { } progress.finish(); } - - private ImageUtils() { - } } diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/MessageNotifyUtil.java b/Core/src/org/sleuthkit/autopsy/coreutils/MessageNotifyUtil.java index 498115f310..22d7b930e6 100644 --- a/Core/src/org/sleuthkit/autopsy/coreutils/MessageNotifyUtil.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/MessageNotifyUtil.java @@ -53,7 +53,9 @@ public class MessageNotifyUtil { INFO(NotifyDescriptor.INFORMATION_MESSAGE, "info-icon-16.png"), //NON-NLS ERROR(NotifyDescriptor.ERROR_MESSAGE, "error-icon-16.png"), //NON-NLS - WARNING(NotifyDescriptor.WARNING_MESSAGE, "warning-icon-16.png"); //NON-NLS + WARNING(NotifyDescriptor.WARNING_MESSAGE, "warning-icon-16.png"), //NON-NLS + CONFIRM(NotifyDescriptor.YES_NO_OPTION, "warning-icon-16.png"); //NON-NLS + private final int notifyDescriptorType; private final Icon icon; @@ -110,6 +112,17 @@ public class MessageNotifyUtil { getDialogDisplayer().notify(new NotifyDescriptor.Message(message, messageType.getNotifyDescriptorType())); } + + /** + * Show an confirm, yes-no dialog + * + * @param message message to show + * @return true if yes is clicked + */ + public static boolean confirm(String message) { + return getDialogDisplayer().notify(new NotifyDescriptor.Confirmation(message, + MessageType.CONFIRM.getNotifyDescriptorType())) == NotifyDescriptor.YES_OPTION; + } /** * Show an information dialog @@ -123,7 +136,7 @@ public class MessageNotifyUtil { /** * Show an error dialog * - * @param message message to shpw + * @param message message to show */ public static void error(String message) { show(message, MessageType.ERROR); @@ -137,6 +150,7 @@ public class MessageNotifyUtil { public static void warn(String message) { show(message, MessageType.WARNING); } + } /** @@ -164,6 +178,10 @@ public class MessageNotifyUtil { /** * Show message with the specified type and action listener + * @param title message title + * @param message message text + * @param type type of the message + * @param actionListener action listener */ public static void show(String title, String message, MessageType type, ActionListener actionListener) { Notification newNotification diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Bundle.properties b/Core/src/org/sleuthkit/autopsy/datamodel/Bundle.properties index bc28375e08..05d385e858 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Bundle.properties @@ -280,3 +280,9 @@ VolumeNode.createSheet.flags.displayName=Flags VolumeNode.createSheet.flags.desc=no description AbstractAbstractFileNode.objectId=Object ID ArtifactStringContent.getStr.artifactId.text=Artifact ID +DeleteReportAction.actionDisplayName.singleReport=Delete Report +DeleteReportAction.actionDisplayName.multipleReports=Delete Reports +DeleteReportAction.actionPerformed.showConfirmDialog.title=Confirm Deletion +DeleteReportAction.actionPerformed.showConfirmDialog.single.msg=Do you want to delete 1 report? +DeleteReportAction.actionPerformed.showConfirmDialog.multiple.msg=Do you want to delete {0} reports? +DeleteReportAction.actionPerformed.showConfirmDialog.checkbox.msg=Check to delete reports from the disk. diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileNode.java index ef7d82e4b8..47f2c30940 100755 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileNode.java @@ -21,10 +21,10 @@ package org.sleuthkit.autopsy.datamodel; import java.util.ArrayList; import java.util.List; import javax.swing.Action; - import org.openide.util.NbBundle; -import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint; import org.sleuthkit.autopsy.actions.AddContentTagAction; +import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint; +import org.sleuthkit.autopsy.coreutils.ImageUtils; import org.sleuthkit.autopsy.directorytree.ExternalViewerAction; import org.sleuthkit.autopsy.directorytree.ExtractAction; import org.sleuthkit.autopsy.directorytree.HashSearchAction; @@ -118,7 +118,7 @@ public class FileNode extends AbstractFsContentNode { // Images for (String s : FileTypeExtensions.getImageExtensions()) { - if (ext.equals(s)) { + if (ImageUtils.thumbnailSupported(file) || ext.equals(s)) { return "org/sleuthkit/autopsy/images/image-file.png"; //NON-NLS } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Reports.java b/Core/src/org/sleuthkit/autopsy/datamodel/Reports.java index 9822227d7a..1dc7910067 100755 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Reports.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Reports.java @@ -27,18 +27,22 @@ import java.io.IOException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.List; import java.util.logging.Level; import javax.swing.AbstractAction; import javax.swing.Action; +import javax.swing.JCheckBox; import javax.swing.JOptionPane; import org.openide.nodes.ChildFactory; import org.openide.nodes.Children; import org.openide.nodes.Node; import org.openide.nodes.Sheet; import org.openide.util.NbBundle; +import org.openide.util.Utilities; import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.corecomponents.DataContentTopComponent; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.Report; import org.sleuthkit.datamodel.TskCoreException; @@ -97,7 +101,7 @@ public final class Reports implements AutopsyVisitableItem { @Override public void propertyChange(PropertyChangeEvent evt) { String eventType = evt.getPropertyName(); - if (eventType.equals(Case.Events.REPORT_ADDED.toString())) { + if (eventType.equals(Case.Events.REPORT_ADDED.toString()) || eventType.equals(Case.Events.REPORT_DELETED.toString())) { ReportNodeFactory.this.refresh(true); } } @@ -183,6 +187,7 @@ public final class Reports implements AutopsyVisitableItem { List actions = new ArrayList<>(); actions.addAll(Arrays.asList(super.getActions(true))); actions.add(new OpenReportAction()); + actions.add(DeleteReportAction.getInstance()); return actions.toArray(new Action[actions.size()]); } @@ -191,6 +196,58 @@ public final class Reports implements AutopsyVisitableItem { return new OpenReportAction(); } + private static class DeleteReportAction extends AbstractAction { + + private static DeleteReportAction instance; + + // This class is a singleton to support multi-selection of nodes, + // since org.openide.nodes.NodeOp.findActions(Node[] nodes) will + // only pick up an Action if every node in the array returns a + // reference to the same action object from Node.getActions(boolean). + private static DeleteReportAction getInstance() { + if (instance == null) { + instance = new DeleteReportAction(); + } + if (Utilities.actionsGlobalContext().lookupAll(Report.class).size() == 1) { + instance.putValue(Action.NAME, NbBundle.getMessage(Reports.class, "DeleteReportAction.actionDisplayName.singleReport")); + } else { + instance.putValue(Action.NAME, NbBundle.getMessage(Reports.class, "DeleteReportAction.actionDisplayName.multipleReports")); + } + return instance; + } + + /** + * Do not instantiate directly. Use + * DeleteReportAction.getInstance(), instead. + */ + private DeleteReportAction() { + } + + @Override + public void actionPerformed(ActionEvent e) { + Collection selectedReportsCollection = Utilities.actionsGlobalContext().lookupAll(Report.class); + + String jOptionPaneMessage = selectedReportsCollection.size() > 1 + ? NbBundle.getMessage(Reports.class, "DeleteReportAction.actionPerformed.showConfirmDialog.multiple.msg", selectedReportsCollection.size()) + : NbBundle.getMessage(Reports.class, "DeleteReportAction.actionPerformed.showConfirmDialog.single.msg"); + JCheckBox checkbox = new JCheckBox(NbBundle.getMessage(Reports.class, "DeleteReportAction.actionPerformed.showConfirmDialog.checkbox.msg")); + checkbox.setSelected(false); + + Object[] jOptionPaneContent = {jOptionPaneMessage, checkbox}; + + if (JOptionPane.showConfirmDialog(null, jOptionPaneContent, + NbBundle.getMessage(Reports.class, "DeleteReportAction.actionPerformed.showConfirmDialog.title"), + JOptionPane.YES_NO_OPTION) == 0) { + try { + Case.getCurrentCase().deleteReports(selectedReportsCollection, checkbox.isSelected()); + DataContentTopComponent.findInstance().repaint(); + } catch (TskCoreException | IllegalStateException ex) { + Logger.getLogger(DeleteReportAction.class.getName()).log(Level.INFO, "Error deleting the reports. ", ex); // NON-NLS - Provide solution to the user? + } + } + } + } + private final class OpenReportAction extends AbstractAction { private OpenReportAction() { diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java index f6fed23038..c620ba01b9 100755 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java @@ -118,7 +118,10 @@ public class DataResultFilterNode extends FilterNode { List actions = new ArrayList<>(); final DisplayableItemNode originalNode = (DisplayableItemNode) this.getOriginal(); - actions.addAll(originalNode.accept(getActionsDIV)); + List accept = originalNode.accept(getActionsDIV); + if(accept != null) { + actions.addAll(accept); + } //actions.add(new IndexContentFilesAction(nodeContent, "Index")); return actions.toArray(new Action[actions.size()]); diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddHashValuesToDatabaseDialog.form b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddHashValuesToDatabaseDialog.form new file mode 100755 index 0000000000..874a617ba1 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddHashValuesToDatabaseDialog.form @@ -0,0 +1,126 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddHashValuesToDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddHashValuesToDatabaseDialog.java new file mode 100755 index 0000000000..b52527dccf --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddHashValuesToDatabaseDialog.java @@ -0,0 +1,231 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2013 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.hashdatabase; + +import java.awt.Dimension; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; +import javax.swing.JFrame; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; +import javax.swing.SwingUtilities; +import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb; +import org.sleuthkit.datamodel.HashEntry; + +/** + * + * @author sidhesh + */ +public class AddHashValuesToDatabaseDialog extends javax.swing.JDialog { + + HashDb hashDb; + Pattern md5Pattern = Pattern.compile("^[a-fA-F0-9]{32}$"); + List hashes = new ArrayList<>(); + List invalidHashes = new ArrayList<>(); + + /** + * Displays a dialog that allows a user to add hash values to the selected + * database. + */ + AddHashValuesToDatabaseDialog(HashDb hashDb) { + super(new JFrame(), + NbBundle.getMessage(AddHashValuesToDatabaseDialog.class, "AddHashValuesToDatabaseDialog.JDialog.Title", hashDb.getHashSetName()), + true); + this.hashDb = hashDb; + initComponents(); + display(); + } + + private void display() { + Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize(); + setLocation((screenDimension.width - getSize().width) / 2, (screenDimension.height - getSize().height) / 2); + setVisible(true); + } + + /** + * Toggle the buttons and default close operation. + * + * @param enable Set true to enable buttons and DISPOSE_ON_CLOSE. Set false + * to disable buttons and DO_NOTHING_ON_CLOSE + */ + void enableAddHashValuesToDatabaseDialog(boolean enable) { + if (enable) { + setDefaultCloseOperation(2); + } else { + setDefaultCloseOperation(0); + } + AddValuesToHashDatabaseButton.setEnabled(enable); + cancelButton.setEnabled(enable); + pasteFromClipboardButton.setEnabled(enable); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + instructionLabel = new javax.swing.JLabel(); + jScrollPane1 = new javax.swing.JScrollPane(); + hashValuesTextArea = new javax.swing.JTextArea(); + pasteFromClipboardButton = new javax.swing.JButton(); + AddValuesToHashDatabaseButton = new javax.swing.JButton(); + cancelButton = new javax.swing.JButton(); + + setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + setTitle(org.openide.util.NbBundle.getMessage(AddHashValuesToDatabaseDialog.class, "AddHashValuesToDatabaseDialog.title")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(instructionLabel, org.openide.util.NbBundle.getMessage(AddHashValuesToDatabaseDialog.class, "AddHashValuesToDatabaseDialog.instructionLabel.text_1")); // NOI18N + + hashValuesTextArea.setColumns(20); + hashValuesTextArea.setRows(5); + hashValuesTextArea.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent evt) { + hashValuesTextAreaMouseClicked(evt); + } + }); + jScrollPane1.setViewportView(hashValuesTextArea); + + org.openide.awt.Mnemonics.setLocalizedText(pasteFromClipboardButton, org.openide.util.NbBundle.getMessage(AddHashValuesToDatabaseDialog.class, "AddHashValuesToDatabaseDialog.pasteFromClipboardButton.text_2")); // NOI18N + pasteFromClipboardButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + pasteFromClipboardButtonActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(AddValuesToHashDatabaseButton, org.openide.util.NbBundle.getMessage(AddHashValuesToDatabaseDialog.class, "AddHashValuesToDatabaseDialog.AddValuesToHashDatabaseButton.text_2")); // NOI18N + AddValuesToHashDatabaseButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + AddValuesToHashDatabaseButtonActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(cancelButton, org.openide.util.NbBundle.getMessage(AddHashValuesToDatabaseDialog.class, "AddHashValuesToDatabaseDialog.cancelButton.text_2")); // NOI18N + cancelButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + cancelButtonActionPerformed(evt); + } + }); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(instructionLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 220, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 41, Short.MAX_VALUE)) + .addComponent(jScrollPane1)) + .addGap(18, 18, 18) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(AddValuesToHashDatabaseButton, javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(cancelButton, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 151, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(pasteFromClipboardButton, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 151, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(instructionLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(AddValuesToHashDatabaseButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(cancelButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(pasteFromClipboardButton)) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 274, Short.MAX_VALUE)) + .addContainerGap()) + ); + + pack(); + }// //GEN-END:initComponents + + private void pasteFromClipboardButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pasteFromClipboardButtonActionPerformed + hashValuesTextArea.paste(); + hashValuesTextArea.append("\n"); + // TODO - Avoid unnecessary \n appending in case nothing is pasted. + }//GEN-LAST:event_pasteFromClipboardButtonActionPerformed + + private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed + this.dispose(); + }//GEN-LAST:event_cancelButtonActionPerformed + + private void hashValuesTextAreaMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_hashValuesTextAreaMouseClicked + if (SwingUtilities.isRightMouseButton(evt)) { + JPopupMenu popup = new JPopupMenu(); + + JMenuItem cutMenu = new JMenuItem("Cut"); // NON-NLS + cutMenu.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + hashValuesTextArea.cut(); + } + }); + + JMenuItem copyMenu = new JMenuItem("Copy"); // NON-NLS + copyMenu.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + hashValuesTextArea.copy(); + } + }); + + JMenuItem pasteMenu = new JMenuItem("Paste"); // NON-NLS + pasteMenu.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + hashValuesTextArea.paste(); + hashValuesTextArea.append("\n"); + } + }); + + popup.add(cutMenu); + popup.add(copyMenu); + popup.add(pasteMenu); + popup.show(hashValuesTextArea, evt.getX(), evt.getY()); + } + }//GEN-LAST:event_hashValuesTextAreaMouseClicked + + private void AddValuesToHashDatabaseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_AddValuesToHashDatabaseButtonActionPerformed + AddHashValuesToDatabaseProgressDialog progressDialog = new AddHashValuesToDatabaseProgressDialog(this, hashDb, hashValuesTextArea.getText()); + progressDialog.addHashValuesToDatabase(); + }//GEN-LAST:event_AddValuesToHashDatabaseButtonActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton AddValuesToHashDatabaseButton; + private javax.swing.JButton cancelButton; + private javax.swing.JTextArea hashValuesTextArea; + private javax.swing.JLabel instructionLabel; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JButton pasteFromClipboardButton; + // End of variables declaration//GEN-END:variables +} diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddHashValuesToDatabaseProgressDialog.form b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddHashValuesToDatabaseProgressDialog.form new file mode 100755 index 0000000000..6d50bbfce6 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddHashValuesToDatabaseProgressDialog.form @@ -0,0 +1,105 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddHashValuesToDatabaseProgressDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddHashValuesToDatabaseProgressDialog.java new file mode 100755 index 0000000000..69fef89521 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/AddHashValuesToDatabaseProgressDialog.java @@ -0,0 +1,273 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2013 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.hashdatabase; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Toolkit; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.SwingWorker; +import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb; +import org.sleuthkit.datamodel.HashEntry; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * + * @author sidhesh + */ +public class AddHashValuesToDatabaseProgressDialog extends javax.swing.JDialog { + + private final AddHashValuesToDatabaseDialog parentRef; + private boolean disposeParent = false; + private final HashDb hashDb; + private final List hashes; + private final List invalidHashes; + private final Pattern md5Pattern; + private String errorTitle; + private String errorMessage; + private final String text; + + /** + * Creates new form AddHashValuesToDatabaseProgressDialog + * + * @param parent + * @param hashDb + * @param text + */ + AddHashValuesToDatabaseProgressDialog(AddHashValuesToDatabaseDialog parent, HashDb hashDb, String text) { + super(parent); + initComponents(); + display(); + this.hashes = new ArrayList<>(); + this.invalidHashes = new ArrayList<>(); + this.md5Pattern = Pattern.compile("^[a-fA-F0-9]{32}$"); // NON-NLS + this.parentRef = parent; + this.hashDb = hashDb; + this.text = text; + } + + private void display() { + Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize(); + setLocation((screenDimension.width - getSize().width) / 2, (screenDimension.height - getSize().height) / 2); + setVisible(true); + } + + /** + * Executes a SwingWorker which performs addition of hashes into the + * database. + */ + final void addHashValuesToDatabase() { + parentRef.enableAddHashValuesToDatabaseDialog(false); + new SwingWorker() { + + @Override + protected Object doInBackground() throws Exception { + // parse the text for md5 hashes. + statusLabel.setText(NbBundle.getMessage(AddHashValuesToDatabaseProgressDialog.class, "AddHashValuesToDatabaseProgressDialog.addHashValuesToDatabase.parsing")); + getHashesFromTextArea(text); + + // Perform checks for invalid input. Then perform insertion + // of hashes in the database. + if (!invalidHashes.isEmpty()) { + statusLabel.setText(NbBundle.getMessage(AddHashValuesToDatabaseProgressDialog.class, "AddHashValuesToDatabaseProgressDialog.addHashValuesToDatabase.invalidHash")); + finish(false); + errorTitle = NbBundle.getMessage(AddHashValuesToDatabaseProgressDialog.class, "AddHashValuesToDatabaseProgressDialog.addHashValuesToDatabase.invaliHash.msg"); + errorMessage = ""; + for (String invalidHash : invalidHashes) { + errorMessage = errorMessage + invalidHash + "\n"; // NON-NLS + } + showErrorsButton.setVisible(true); + showErrorsButton.requestFocus(); + } else if (hashes.isEmpty()) { + statusLabel.setText(NbBundle.getMessage(AddHashValuesToDatabaseProgressDialog.class, "AddHashValuesToDatabaseProgressDialog.addHashValuesToDatabase.noHashesToAdd")); + finish(false); + } else { + try { + hashDb.addHashes(hashes); + okButton.requestFocus(); + statusLabel.setText(NbBundle.getMessage(AddHashValuesToDatabaseProgressDialog.class, "AddHashValuesToDatabaseProgressDialog.addHashValuesToDatabase.success", hashes.size())); + finish(true); + disposeParent = true; + } catch (TskCoreException ex) { + statusLabel.setText(NbBundle.getMessage(AddHashValuesToDatabaseProgressDialog.class, "AddHashValuesToDatabaseProgressDialog.addHashValuesToDatabase.errorAddingValidHash")); + finish(false); + errorTitle = NbBundle.getMessage(AddHashValuesToDatabaseProgressDialog.class, "AddHashValuesToDatabaseProgressDialog.addHashValuesToDatabase.errorAddingValidHash.msg"); + errorMessage = ex.toString(); + showErrorsButton.setVisible(true); + showErrorsButton.requestFocus(); + } + } + return null; + } + }.execute(); + } + + /** + * Sets the progressbar to maximum value, change colors accordingly, and + * enables OK button. + * + * @param success + */ + private void finish(boolean success) { + okButton.setEnabled(true); + addingHashesToDatabaseProgressBar.setIndeterminate(false); + addingHashesToDatabaseProgressBar.setValue(addingHashesToDatabaseProgressBar.getMaximum()); + if (success) { + // a hack to set progressbar color. + addingHashesToDatabaseProgressBar.setStringPainted(true); + addingHashesToDatabaseProgressBar.setForeground(new Color(50,205,50)); + addingHashesToDatabaseProgressBar.setString(""); + } else { + // a hack to set progressbar color. + addingHashesToDatabaseProgressBar.setStringPainted(true); + addingHashesToDatabaseProgressBar.setForeground(new Color(178,34,34)); + addingHashesToDatabaseProgressBar.setString(""); + } + + } + + /** + * Parses for String for MD5 hashes and adds new HashEntry objects into the + * list of hashes. It also populates the invalidHashes list for + * user-feedback. + * + * @param text + */ + private void getHashesFromTextArea(String text) { + String[] linesInTextArea = text.split("\\r?\\n"); // NON-NLS + // These entries may be of or format + for (String hashEntry : linesInTextArea) { + hashEntry = hashEntry.trim(); + Matcher m = md5Pattern.matcher(hashEntry); + if (m.find()) { + // more information can be added to the HashEntry - sha-1, sha-512, comment + hashes.add(new HashEntry(null, m.group(0), null, null, null)); + } else { + if (!hashEntry.isEmpty()) { + invalidHashes.add(hashEntry); + } + } + } + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + addingHashesToDatabaseProgressBar = new javax.swing.JProgressBar(); + okButton = new javax.swing.JButton(); + statusLabel = new javax.swing.JLabel(); + showErrorsButton = new javax.swing.JButton(); + + setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE); + setTitle(org.openide.util.NbBundle.getMessage(AddHashValuesToDatabaseProgressDialog.class, "AddHashValuesToDatabaseProgressDialog.title")); // NOI18N + + addingHashesToDatabaseProgressBar.setIndeterminate(true); + + org.openide.awt.Mnemonics.setLocalizedText(okButton, org.openide.util.NbBundle.getMessage(AddHashValuesToDatabaseProgressDialog.class, "AddHashValuesToDatabaseProgressDialog.okButton.text")); // NOI18N + okButton.setEnabled(false); + okButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + okButtonActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(statusLabel, org.openide.util.NbBundle.getMessage(AddHashValuesToDatabaseProgressDialog.class, "AddHashValuesToDatabaseProgressDialog.statusLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(showErrorsButton, org.openide.util.NbBundle.getMessage(AddHashValuesToDatabaseProgressDialog.class, "AddHashValuesToDatabaseProgressDialog.showErrorsButton.text")); // NOI18N + showErrorsButton.setVisible(false); + showErrorsButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + showErrorsButtonActionPerformed(evt); + } + }); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addGroup(layout.createSequentialGroup() + .addComponent(statusLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(showErrorsButton)) + .addGroup(layout.createSequentialGroup() + .addComponent(addingHashesToDatabaseProgressBar, javax.swing.GroupLayout.PREFERRED_SIZE, 300, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(18, 18, 18) + .addComponent(okButton, javax.swing.GroupLayout.PREFERRED_SIZE, 91, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(addingHashesToDatabaseProgressBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(okButton)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(showErrorsButton) + .addComponent(statusLabel)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + + pack(); + }// //GEN-END:initComponents + + private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed + parentRef.enableAddHashValuesToDatabaseDialog(true); + if (disposeParent) { + parentRef.dispose(); + } + this.dispose(); + }//GEN-LAST:event_okButtonActionPerformed + + private void showErrorsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showErrorsButtonActionPerformed + JLabel textLabel = new JLabel(errorTitle); + JTextArea textArea = new JTextArea(errorMessage); + textArea.setEditable(false); + JScrollPane scrollPane = new JScrollPane(textArea); + scrollPane.setPreferredSize(new Dimension(250, 100)); + Object[] jOptionPaneComponents = {textLabel, scrollPane}; + JOptionPane.showMessageDialog(this, jOptionPaneComponents, "Error:\n", JOptionPane.OK_OPTION); // NON-NLS + }//GEN-LAST:event_showErrorsButtonActionPerformed + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JProgressBar addingHashesToDatabaseProgressBar; + private javax.swing.JButton okButton; + private javax.swing.JButton showErrorsButton; + private javax.swing.JLabel statusLabel; + // End of variables declaration//GEN-END:variables +} diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties index 59388a4aa1..6143caecc7 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties @@ -196,3 +196,21 @@ HashLookupModuleFactory.getIngestJobSettingsPanel.exception.msg=Expected setting HashLookupModuleFactory.createFileIngestModule.exception.msg=Expected settings argument to be instanceof HashLookupModuleSettings HashLookupModuleSettingsPanel.alwaysCalcHashesCheckbox.toolTipText=Calculate MD5 even if no hash database is selected HashDbSearchPanel.hashTable.defaultModel.title.text=MD5 Hashes +AddHashValuesToDatabaseDialog.JDialog.Title=Add Hashes to Database +HashLookupSettingsPanel.addHashesToDatabaseButton.text=Add Hashes to Database +AddHashValuesToDatabaseDialog.instructionLabel.text_1=Paste MD5 hash values (one per line) below: +AddHashValuesToDatabaseDialog.cancelButton.text_2=Cancel +AddHashValuesToDatabaseDialog.AddValuesToHashDatabaseButton.text_2=Add Hashes to Database +AddHashValuesToDatabaseDialog.pasteFromClipboardButton.text_2=Paste From Clipboard +AddHashValuesToDatabaseProgressDialog.okButton.text=OK +AddHashValuesToDatabaseProgressDialog.statusLabel.text=status +AddHashValuesToDatabaseProgressDialog.title=Add Hashes to Database Progress +AddHashValuesToDatabaseDialog.title=Add Hashes to Database +AddHashValuesToDatabaseProgressDialog.showErrorsButton.text=Show Errors +AddHashValuesToDatabaseProgressDialog.addHashValuesToDatabase.parsing=Parsing text for MD5 hashes... +AddHashValuesToDatabaseProgressDialog.addHashValuesToDatabase.invalidHash=The input contains invalid hash. +AddHashValuesToDatabaseProgressDialog.addHashValuesToDatabase.invaliHash.msg=Invalid Hashes: +AddHashValuesToDatabaseProgressDialog.addHashValuesToDatabase.noHashesToAdd=There are no hashes to add. +AddHashValuesToDatabaseProgressDialog.addHashValuesToDatabase.success={0} Hashes added successfully. +AddHashValuesToDatabaseProgressDialog.addHashValuesToDatabase.errorAddingValidHash=There is an error adding valid hashes. +AddHashValuesToDatabaseProgressDialog.addHashValuesToDatabase.errorAddingValidHash.msg=Error adding valid hashes to the database: \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle_ja.properties index 912a9db79c..90c7f77266 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle_ja.properties @@ -1,194 +1,194 @@ -OpenIDE-Module-Display-Category=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB +OpenIDE-Module-Display-Category=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb OpenIDE-Module-Long-Description=\ - \u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB \n\n\ - \u30C7\u30A3\u30B9\u30AF\u30A4\u30E1\u30FC\u30B8\u306B\u3042\u308B\u30D5\u30A1\u30A4\u30EB\u3092\u89E3\u6790\u3057\u3001\u300C\u65E2\u77E5\u300D\uFF08NSRL\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306E\u300C\u65E2\u77E5\u300D\u30D5\u30A1\u30A4\u30EB\u30EB\u30C3\u30AF\u30A2\u30C3\u30D7\u3092\u57FA\u306B\uFF09\u307E\u305F\u306F\u300C\u60AA\u8CEA\uFF0F\u7591\u308F\u3057\u3044\u300D\uFF08\u30E6\u30FC\u30B6\u30FC\u304C\u6307\u5B9A\u3057\u305F\uFF11\u3064\u307E\u305F\u306F\u8907\u6570\u306E\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u57FA\u306B\uFF09\u3068\u30DE\u30FC\u30AF\u3057\u307E\u3059\u3002\n\n\ - \u30CF\u30C3\u30B7\u30E5\u3084\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u8A2D\u5B9A\u306B\u57FA\u3065\u3044\u305F\u30D5\u30A1\u30A4\u30EB\u30EB\u30C3\u30AF\u30A2\u30C3\u30D7\u306A\u3069\u3001\u3053\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u306FGUI\u306B\u9023\u643A\u3057\u3066\u3044\u308B\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u3057\u306A\u3044\u3001\u8FFD\u52A0\u306E\u30C4\u30FC\u30EB\u304C\u542B\u307E\u308C\u307E\u3059\u3002 -OpenIDE-Module-Name=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9 -HashDbSearchPanel.hashTable.columnModel.title0=MD5\u30CF\u30C3\u30B7\u30E5 -HashDbSearchPanel.addButton.text=\u30CF\u30C3\u30B7\u30E5\u3092\u8FFD\u52A0 -HashDbSearchPanel.hashLabel.text=MD5\u30CF\u30C3\u30B7\u30E5\uFF1A -HashDbSearchPanel.searchButton.text=\u691C\u7D22 -HashDbSearchPanel.removeButton.text=\u9078\u629E\u3057\u305F\u3082\u306E\u3092\u524A\u9664 -HashDbSearchPanel.titleLabel.text=\u4E0B\u8A18\u306EMD5\u30CF\u30C3\u30B7\u30E5\u4ED8\u304D\u306E\u30D5\u30A1\u30A4\u30EB\u3092\u691C\u7D22\uFF1A -HashDbSearchPanel.errorField.text=\u30A8\u30E9\u30FC\uFF1A\u5168\u3066\u306E\u30D5\u30A1\u30A4\u30EB\u304C\u30CF\u30C3\u30B7\u30E5\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F\u3002 -HashDbSearchPanel.saveBox.text=\u30CF\u30C3\u30B7\u30E5\u3092\u8A18\u61B6 -HashDbSearchPanel.cancelButton.text=\u30AD\u30E3\u30F3\u30BB\u30EB -OpenIDE-Module-Short-Description=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u304A\u3088\u3073\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30C4\u30FC\u30EB -HashDbImportDatabaseDialog.jLabel1.text=\u30CF\u30C3\u30B7\u30E5\u30BB\u30C3\u30C8\u540D\uFF1A -HashDbImportDatabaseDialog.knownBadRadioButton.text=\u65E2\u77E5\u306E\u60AA\u8CEA -HashDbImportDatabaseDialog.jLabel2.text=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306E\u30BF\u30A4\u30D7\uFF1A + \u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb \n\n\ + \u30c7\u30a3\u30b9\u30af\u30a4\u30e1\u30fc\u30b8\u306b\u3042\u308b\u30d5\u30a1\u30a4\u30eb\u3092\u89e3\u6790\u3057\u3001\u300c\u65e2\u77e5\u300d\uff08NSRL\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u300c\u65e2\u77e5\u300d\u30d5\u30a1\u30a4\u30eb\u30eb\u30c3\u30af\u30a2\u30c3\u30d7\u3092\u57fa\u306b\uff09\u307e\u305f\u306f\u300c\u60aa\u8cea\uff0f\u7591\u308f\u3057\u3044\u300d\uff08\u30e6\u30fc\u30b6\u30fc\u304c\u6307\u5b9a\u3057\u305f\uff11\u3064\u307e\u305f\u306f\u8907\u6570\u306e\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u57fa\u306b\uff09\u3068\u30de\u30fc\u30af\u3057\u307e\u3059\u3002\n\n\ + \u30cf\u30c3\u30b7\u30e5\u3084\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u8a2d\u5b9a\u306b\u57fa\u3065\u3044\u305f\u30d5\u30a1\u30a4\u30eb\u30eb\u30c3\u30af\u30a2\u30c3\u30d7\u306a\u3069\u3001\u3053\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u306fGUI\u306b\u9023\u643a\u3057\u3066\u3044\u308b\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3057\u306a\u3044\u3001\u8ffd\u52a0\u306e\u30c4\u30fc\u30eb\u304c\u542b\u307e\u308c\u307e\u3059\u3002 +OpenIDE-Module-Name=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9 +HashDbSearchPanel.hashTable.columnModel.title0=MD5\u30cf\u30c3\u30b7\u30e5 +HashDbSearchPanel.addButton.text=\u30cf\u30c3\u30b7\u30e5\u3092\u8ffd\u52a0 +HashDbSearchPanel.hashLabel.text=MD5\u30cf\u30c3\u30b7\u30e5\uff1a +HashDbSearchPanel.searchButton.text=\u691c\u7d22 +HashDbSearchPanel.removeButton.text=\u9078\u629e\u3057\u305f\u3082\u306e\u3092\u524a\u9664 +HashDbSearchPanel.titleLabel.text=\u4e0b\u8a18\u306eMD5\u30cf\u30c3\u30b7\u30e5\u4ed8\u304d\u306e\u30d5\u30a1\u30a4\u30eb\u3092\u691c\u7d22\uff1a +HashDbSearchPanel.errorField.text=\u30a8\u30e9\u30fc\uff1a\u5168\u3066\u306e\u30d5\u30a1\u30a4\u30eb\u304c\u30cf\u30c3\u30b7\u30e5\u3055\u308c\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +HashDbSearchPanel.saveBox.text=\u30cf\u30c3\u30b7\u30e5\u3092\u8a18\u61b6 +HashDbSearchPanel.cancelButton.text=\u30ad\u30e3\u30f3\u30bb\u30eb +OpenIDE-Module-Short-Description=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u304a\u3088\u3073\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30c4\u30fc\u30eb +HashDbImportDatabaseDialog.jLabel1.text=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u540d\uff1a +HashDbImportDatabaseDialog.knownBadRadioButton.text=\u65e2\u77e5\u306e\u60aa\u8cea +HashDbImportDatabaseDialog.jLabel2.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30bf\u30a4\u30d7\uff1a HashDbImportDatabaseDialog.okButton.text=OK -HashDbImportDatabaseDialog.cancelButton.text=\u30AD\u30E3\u30F3\u30BB\u30EB -HashDbCreateDatabaseDialog.jLabel2.text=\u30BF\u30A4\u30D7\uFF1A -HashDbCreateDatabaseDialog.knownBadRadioButton.text=\u65E2\u77E5\u306E\u60AA\u8CEA -HashDbCreateDatabaseDialog.cancelButton.text=\u30AD\u30E3\u30F3\u30BB\u30EB -ModalNoButtons.CURRENTLYON_LABEL.text=y\u306Ex\u3092\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u4E2D -ModalNoButtons.GO_GET_COFFEE_LABEL.text=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u4E2D\u3067\u3059\u3002\u6642\u9593\u304C\u304B\u304B\u308B\u5834\u5408\u304C\u3042\u308A\u307E\u3059\u3002 -ModalNoButtons.CANCEL_BUTTON.text=\u30AD\u30E3\u30F3\u30BB\u30EB -HashDbImportDatabaseDialog.knownRadioButton.text=\u65E2\u77E5\uFF08NSRL\u307E\u305F\u306F\u305D\u306E\u4ED6\uFF09 -HashDbCreateDatabaseDialog.knownRadioButton.text=\u65E2\u77E5 -HashDbCreateDatabaseDialog.jLabel1.text=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30D1\u30B9\uFF1A -HashDbCreateDatabaseDialog.saveAsButton.text=\u540D\u524D\u3092\u3064\u3051\u3066\u4FDD\u5B58\u2026 -HashDbImportDatabaseDialog.jLabel3.text=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30D1\u30B9\uFF1A -HashDbCreateDatabaseDialog.sendIngestMessagesCheckbox.text=\u30D2\u30C3\u30C8\u6BCE\u306B\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30A4\u30F3\u30DC\u30C3\u30AF\u30B9\u306B\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u9001\u308B -HashDbImportDatabaseDialog.sendIngestMessagesCheckbox.text=\u30D2\u30C3\u30C8\u6BCE\u306B\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30A4\u30F3\u30DC\u30C3\u30AF\u30B9\u306B\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u9001\u308B -HashDbImportDatabaseDialog.openButton.text=\u958B\u304F... -HashDbCreateDatabaseDialog.jLabel3.text=\u30CF\u30C3\u30B7\u30E5\u30BB\u30C3\u30C8\u540D\uFF1A +HashDbImportDatabaseDialog.cancelButton.text=\u30ad\u30e3\u30f3\u30bb\u30eb +HashDbCreateDatabaseDialog.jLabel2.text=\u30bf\u30a4\u30d7\uff1a +HashDbCreateDatabaseDialog.knownBadRadioButton.text=\u65e2\u77e5\u306e\u60aa\u8cea +HashDbCreateDatabaseDialog.cancelButton.text=\u30ad\u30e3\u30f3\u30bb\u30eb +ModalNoButtons.CURRENTLYON_LABEL.text=y\u306ex\u3092\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u4e2d +ModalNoButtons.GO_GET_COFFEE_LABEL.text=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u4e2d\u3067\u3059\u3002\u6642\u9593\u304c\u304b\u304b\u308b\u5834\u5408\u304c\u3042\u308a\u307e\u3059\u3002 +ModalNoButtons.CANCEL_BUTTON.text=\u30ad\u30e3\u30f3\u30bb\u30eb +HashDbImportDatabaseDialog.knownRadioButton.text=\u65e2\u77e5\uff08NSRL\u307e\u305f\u306f\u305d\u306e\u4ed6\uff09 +HashDbCreateDatabaseDialog.knownRadioButton.text=\u65e2\u77e5 +HashDbCreateDatabaseDialog.jLabel1.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30d1\u30b9\uff1a +HashDbCreateDatabaseDialog.saveAsButton.text=\u540d\u524d\u3092\u3064\u3051\u3066\u4fdd\u5b58\u2026 +HashDbImportDatabaseDialog.jLabel3.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30d1\u30b9\uff1a +HashDbCreateDatabaseDialog.sendIngestMessagesCheckbox.text=\u30d2\u30c3\u30c8\u6bce\u306b\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30a4\u30f3\u30dc\u30c3\u30af\u30b9\u306b\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u9001\u308b +HashDbImportDatabaseDialog.sendIngestMessagesCheckbox.text=\u30d2\u30c3\u30c8\u6bce\u306b\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30a4\u30f3\u30dc\u30c3\u30af\u30b9\u306b\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u9001\u308b +HashDbImportDatabaseDialog.openButton.text=\u958b\u304f... +HashDbCreateDatabaseDialog.jLabel3.text=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u540d\uff1a HashDbCreateDatabaseDialog.okButton.text=OK -AddContentToHashDbAction.ContentMenu.noHashDbsConfigd=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093 -AddContentToHashDbAction.ContentMenu.createDbItem=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u4F5C\u6210... -AddContentToHashDbAction.addFilesToHashSet.addToHashDbErr1.text=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30A8\u30E9\u30FC\u306B\u8FFD\u52A0 -AddContentToHashDbAction.addFilesToHashSet.addToHashDbErr2.text=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30A8\u30E9\u30FC\u306B\u8FFD\u52A0 -AddContentToHashDbAction.addFilesToHashSet.addToHashDbErr3.text=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30A8\u30E9\u30FC\u306B\u8FFD\u52A0 -AddContentToHashDbAction.addFilesToHashSet.unableToAddFileMsg=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306B{0}\u3092\u8FFD\u52A0\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002 -AddContentToHashDbAction.addFilesToHashSet.unableToAddFileSzMsg=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306B{0}\u3092\u8FFD\u52A0\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u30CF\u30C3\u30B7\u30E5\u5024\u304C\u8A08\u7B97\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002\u9069\u5207\u306A\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u8A2D\u5B9A\u3057\u3001\u5B9F\u884C\u3057\u3066\u4E0B\u3055\u3044\u3002 -HashDatabaseOptionsPanelController.moduleErr=\u30E2\u30B8\u30E5\u30FC\u30EB\u30A8\u30E9\u30FC -HashDatabaseOptionsPanelController.moduleErrMsg=HashDatabaseOptionsPanelController\u306E\u30A2\u30C3\u30D7\u30C7\u30FC\u30C8\u3092\u78BA\u8A8D\u4E2D\u306B\u30E2\u30B8\u30E5\u30FC\u30EB\u304C\u30A8\u30E9\u30FC\u3092\u8D77\u3053\u3057\u307E\u3057\u305F\u3002\u3069\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u304B\u30ED\u30B0\u3067\u78BA\u8A8D\u3057\u3066\u4E0B\u3055\u3044\u3002\u4E00\u90E8\u306E\u30C7\u30FC\u30BF\u304C\u5B8C\u5168\u3067\u306A\u3044\u3053\u3068\u304C\u3042\u308A\u307E\u3059\u3002 -HashDbConfigPanel.noSelectionText=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304C\u9078\u629E\u3055\u308C\u3066\u3044\u307E\u305B\u3093 -HashDbConfigPanel.errorGettingPathText=\u30D1\u30B9\u306E\u53D6\u5F97\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F -HashDbConfigPanel.errorGettingIndexStatusText=\u30B9\u30C6\u30FC\u30BF\u30B9\u306E\u78BA\u8A8D\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F -HashDbConfigPanel.setName.hashSetConfig=\u30CF\u30C3\u30B7\u30E5\u30BB\u30C3\u30C8\u8A2D\u5B9A -HashDbConfigPanel.indexButtonText.index=\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9 -HashDbConfigPanel.indexButtonText.indexing=\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u4E2D -HashDbConfigPanel.indexStatusText.indexGen=\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u3092\u4F5C\u6210\u4E2D\u3067\u3059 -HashDbConfigPanel.indexStatusText.indexOnly=\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u306E\u307F -HashDbConfigPanel.indexStatusText.indexed=\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u6E08\u307F -HashDbConfigPanel.indexButtonText.reIndex=\u518D\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9 -HashDbConfigPanel.indexStatusText.noIndex=\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u7121\u3057 -HashDbConfigPanel.dbsNotIndexedMsg=\u4E0B\u8A18\u306E\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306F\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u3057\u307E\u3059\u304B\uFF1F\n {0} -HashDbConfigPanel.unindexedDbsMsg=\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u3055\u308C\u3066\u3044\u306A\u3044\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9 -HashDbConfigPanel.allUnindexedDbsRmFromListMsg=\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u3055\u308C\u3066\u3044\u306A\u3044\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306F\u30EA\u30B9\u30C8\u304B\u3089\u524A\u9664\u3055\u308C\u307E\u3059 -HashDbConfigPanel.nameColLbl=\u540D\u524D -HashDbConfigPanel.editingCellsNotSupportedMsg=\u30BB\u30EB\u306F\u7DE8\u96C6\u4E0D\u53EF\u3067\u3059 -HashDbConfigPanel.deleteDbActionConfirmMsg=\u5168\u3066\u306E\u30B1\u30FC\u30B9\u306B\u304A\u3051\u308B\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u524A\u9664\u3057\u307E\u3059\u3002\u5B9F\u884C\u3057\u307E\u3059\u304B\uFF1F -HashDbConfigPanel.deleteDbActionMsg=\u8A2D\u5B9A\u304B\u3089\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u524A\u9664 -HashDbCreateDatabaseDialog.createHashDbMsg=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u4F5C\u6210 -HashDbCreateDatabaseDialog.hashDbMustHaveFileExtensionMsg=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30D5\u30A1\u30A4\u30EB\u306F .{0} \u306E\u62E1\u5F35\u5B50\u304C\u5FC5\u8981\u3067\u3059\u3002 -HashDbCreateDatabaseDialog.fileNameErr=\u30D5\u30A1\u30A4\u30EB\u540D\u30A8\u30E9\u30FC -HashDbCreateDatabaseDialog.fileNameAlreadyExistsMsg=\u540C\u540D\u306E\u30D5\u30A1\u30A4\u30EB\u304C\u65E2\u306B\u5B58\u5728\u3057\u307E\u3059\u3002\u5225\u306E\u30D5\u30A1\u30A4\u30EB\u540D\u3092\u8A2D\u5B9A\u3057\u3066\u4E0B\u3055\u3044\u3002 -HashDbCreateDatabaseDialog.fileExistsErr=\u30D5\u30A1\u30A4\u30EB\u304C\u65E2\u306B\u5B58\u5728\u3057\u3066\u3044\u308B\u30A8\u30E9\u30FC -HashDbCreateDatabaseDialog.mustEnterHashSetNameMsg=\u30CF\u30C3\u30B7\u30E5\u30BB\u30C3\u30C8\u540D\u306E\u5165\u529B\u304C\u5FC5\u8981\u3067\u3059 -HashDbCreateDatabaseDialog.createHashDbErr=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u4F5C\u6210\u30A8\u30E9\u30FC -HashDbCreateDatabaseDialog.mustEnterHashDbPathMsg=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30D1\u30B9\u306E\u5165\u529B\u304C\u5FC5\u8981\u3067\u3059\u3002 -HashDbCreateDatabaseDialog.errMsg.hashDbCreationErr=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u4F5C\u6210\u30A8\u30E9\u30FC -HashDbCreateDatabaseDialog.cannotCreateFileAtLocMsg=\u6307\u5B9A\u3055\u308C\u305F\u30ED\u30B1\u30FC\u30B7\u30E7\u30F3\u3067\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30D5\u30A1\u30A4\u30EB\u3092\u4F5C\u6210\u3067\u304D\u307E\u305B\u3093\u3002 -HashDbCreateDatabaseDialog.failedToCreateHashDbMsg=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306E\u4F5C\u6210\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002 -HashDbImportDatabaseDialog.importHashDbMsg=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u30A4\u30F3\u30DD\u30FC\u30C8 -HashDbImportDatabaseDialog.fileNameExtFilter.text=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30D5\u30A1\u30A4\u30EB -HashDbImportDatabaseDialog.failedToGetDbPathMsg=\u9078\u629E\u3057\u305F\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306E\u30D1\u30B9\u306E\u5165\u624B\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002 -HashDbImportDatabaseDialog.importHashDbErr=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306E\u30A4\u30F3\u30DD\u30FC\u30C8\u30A8\u30E9\u30FC -HashDbImportDatabaseDialog.mustSelectHashDbFilePathMsg=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30D5\u30A1\u30A4\u30EB\u30D1\u30B9\u306E\u9078\u629E\u304C\u5FC5\u8981\u3067\u3059\u3002 -HashDbImportDatabaseDialog.hashDbDoesNotExistMsg=\u9078\u629E\u3055\u308C\u305F\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306F\u5B58\u5728\u3057\u307E\u305B\u3093\u3002 -HashDbImportDatabaseDialog.errorMessage.failedToOpenHashDbMsg={0}\u3067\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u958B\u304F\u306E\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002 -HashDbIngestModule.moduleName=\u30CF\u30C3\u30B7\u30E5\u30EB\u30C3\u30AF\u30A2\u30C3\u30D7 -HashDbIngestModule.moduleDescription=\u6A19\u6E96\u306ENSRL\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306A\u3069\u3001\u63D0\u4F9B\u3055\u308C\u305F\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u5229\u7528\u3057\u3066\u3001\u65E2\u77E5\u307E\u305F\u306F\u7591\u308F\u3057\u3044\u3082\u306E\u3092\u7279\u5B9A\u3057\u307E\u3059\u3002 -HashDbIngestModule.noKnownHashDbSetMsg=\u65E2\u77E5\u306E\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304C\u5B58\u5728\u3057\u307E\u305B\u3093\u3002 -HashDbIngestModule.knownFileSearchWillNotExecuteWarn=\u65E2\u77E5\u306E\u30D5\u30A1\u30A4\u30EB\u691C\u7D22\u304C\u5B9F\u884C\u3055\u308C\u307E\u305B\u3093\u3002 -HashDbIngestModule.noKnownBadHashDbSetMsg=\u65E2\u77E5\u306E\u60AA\u8CEA\u306A\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30BB\u30C3\u30C8\u306F\u3042\u308A\u307E\u305B\u3093\u3002 -HashDbConfigPanel.dbNotIndexedMsg=\u4E0B\u8A18\u306E\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306F\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u3057\u307E\u3059\u304B\uFF1F\n{0} -HashDbIngestModule.knownBadFileSearchWillNotExecuteWarn=\u65E2\u77E5\u306E\u60AA\u8CEA\u30D5\u30A1\u30A4\u30EB\u691C\u7D22\u306F\u5B9F\u884C\u3055\u308C\u307E\u305B\u3093\u3002 -HashDbIngestModule.fileReadErrorMsg=\u8AAD\u307F\u8FBC\u307F\u30A8\u30E9\u30FC\uFF1A {0} -HashDbIngestModule.calcHashValueErr={0}\u306E\u30CF\u30C3\u30B7\u30E5\u5024\u3092\u8A08\u7B97\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002 -HashDbIngestModule.hashLookupErrorMsg=\u30CF\u30C3\u30B7\u30E5\u30EB\u30C3\u30AF\u30A2\u30C3\u30D7\u30A8\u30E9\u30FC\uFF1A {0} -HashDbIngestModule.settingKnownBadStateErr={0}\u306E\u30B9\u30C6\u30FC\u30BF\u30B9\u3092\u65E2\u77E5\u306E\u60AA\u8CEA\u3068\u8A2D\u5B9A\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002 -HashDbIngestModule.lookingUpKnownBadHashValueErr={0}\u306E\u65E2\u77E5\u306E\u60AA\u8CEA\u30CF\u30C3\u30B7\u30E5\u5024\u3092\u30EB\u30C3\u30AF\u30A2\u30C3\u30D7\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002 -HashDbIngestModule.lookingUpKnownHashValueErr={0}\u306E\u65E2\u77E5\u306E\u60AA\u8CEA\u30CF\u30C3\u30B7\u30E5\u5024\u3092\u30EB\u30C3\u30AF\u30A2\u30C3\u30D7\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002 -HashDbIngestModule.postToBB.fileName=\u30D5\u30A1\u30A4\u30EB\u540D -HashDbIngestModule.postToBB.md5Hash=MD5\u30CF\u30C3\u30B7\u30E5 -HashDbIngestModule.postToBB.hashsetName=\u30CF\u30C3\u30B7\u30E5\u30BB\u30C3\u30C8\u540D -HashDbIngestModule.postToBB.knownBadMsg=\u65E2\u77E5\u306E\u60AA\u8CEA\: {0} -HashDbIngestModule.complete.knownBadsFound=\u767A\u898B\u3055\u308C\u305F\u65E2\u77E5\u306E\u60AA\u8CEA\uFF1A -HashDbIngestModule.complete.totalCalcTime=\u8A08\u7B97\u6642\u9593\u306E\u5408\u8A08 -HashDbIngestModule.complete.totalLookupTime=\u30EB\u30C3\u30AF\u30A2\u30C3\u30D7\u6642\u9593\u306E\u5408\u8A08 -HashDbIngestModule.complete.databasesUsed=\u5229\u7528\u3057\u305F\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\uFF1A -HashDbIngestModule.complete.hashLookupResults=\u30CF\u30C3\u30B7\u30E5\u30EB\u30C3\u30AF\u30A2\u30C3\u30D7\u7D50\u679C -HashDbManager.moduleErrorListeningToUpdatesMsg=HashDbManager\u30A2\u30C3\u30D7\u30C7\u30FC\u30C8\u3092\u78BA\u8A8D\u4E2D\u306B\u30E2\u30B8\u30E5\u30FC\u30EB\u304C\u30A8\u30E9\u30FC\u3092\u8D77\u3053\u3057\u307E\u3057\u305F\u3002\u3069\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u304C\u539F\u56E0\u306A\u306E\u304B\u3092\u30ED\u30B0\u3067\u78BA\u8A8D\u3057\u3066\u4E0B\u3055\u3044\u3002\u4E00\u90E8\u306E\u30C7\u30FC\u30BF\u304C\u5B8C\u5168\u3067\u306A\u3044\u3053\u3068\u304C\u3042\u308A\u307E\u3059\u3002 -HashDbManager.replacingDuplicateHashsetNameMsg=\u8907\u88FD\u306E\u30CF\u30C3\u30B7\u30E5\u30BB\u30C3\u30C8\u540D {0} \u304C\u898B\u3064\u304B\u308A\u307E\u3057\u305F\u3002\n {1}\u306B\u66F8\u304D\u63DB\u3048\u307E\u3059\u3002 -HashDbManager.openHashDbErr=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u958B\u304F\u30A8\u30E9\u30FC -HashDbManager.unableToOpenHashDbMsg=\ {0} \u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u958B\u3051\u307E\u305B\u3093\u3002 -HashDbManager.savedBackupOfOldConfigMsg={0}\n\u53E4\u3044\u8A2D\u5B9A\u306E\u30D0\u30C3\u30AF\u30A2\u30C3\u30D7\u30B3\u30D4\u30FC\u304C\u4E0B\u8A18\u306E\u901A\u308A\u4FDD\u5B58\u3055\u308C\u307E\u3057\u305F\u3002\n{1} -HashDbManager.baseMessage.updatedFormatHashDbConfig=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u8A2D\u5B9A\u30D5\u30A1\u30A4\u30EB\u306E\u5F62\u5F0F\u304C\u66F4\u65B0\u3055\u308C\u307E\u3057\u305F\u3002 -HashDbManager.msgBoxTitle.confFileFmtChanged=\u8A2D\u5B9A\u30D5\u30A1\u30A4\u30EB\u5F62\u5F0F\u306E\u5909\u66F4\u5B8C\u4E86 -HashDbManager.dlgMsg.dbNotFoundAtLoc=\ {0} \u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306F\u4E0B\u8A18\u306E\u30ED\u30B1\u30FC\u30B7\u30E7\u30F3\u306B\u3042\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002\n {1}\n \u30D5\u30A1\u30A4\u30EB\u3092\u691C\u7D22\u3057\u307E\u3059\u304B\uFF1F -HashDbManager.dlgTitle.MissingDb=\u6B20\u843D\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9 -HashDbManager.progress.indexingHashSet=\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u4E2D {0} -HashDbManager.dlgMsg.errorIndexingHashSet=\ {0} \u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306E\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u4E2D\u306E\u30A8\u30E9\u30FC -HashDbManager.hashDbIndexingErr=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306E\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u4E2D\u306E\u30A8\u30E9\u30FC -HashDbPanelSearchAction.actionName=MD5\u30CF\u30C3\u30B7\u30E5\u306B\u57FA\u3065\u304F\u30D5\u30A1\u30A4\u30EB\u691C\u7D22 -HashDbSearchAction.dlgMsg.noFilesHaveMD5Calculated=MD5\u30CF\u30C3\u30B7\u30E5\u304C\u8A08\u7B97\u3055\u308C\u3066\u3044\u308B\u30D5\u30A1\u30A4\u30EB\u304C\u3042\u308A\u307E\u305B\u3093\u3002\u307E\u305A\u306FHashDB\u3092\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u3057\u3066\u4E0B\u3055\u3044\u3002 -HashDbSearchManager.MD5HashSearch=MD5\u30CF\u30C3\u30B7\u30E5\u691C\u7D22 -HashDbSearchManager.noResultsFoundMsg=\u4E00\u81F4\u3059\u308B\u3082\u306E\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002 -HashDbSearchPanel.titleText.ingestOngoing=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u4E2D\uFF1B\u5B8C\u4E86\u3059\u308B\u307E\u3067\u3053\u306E\u30B5\u30FC\u30D3\u30B9\u306F\u5229\u7528\u3067\u304D\u307E\u305B\u3093\u3002 -HashDbSearchPanel.noFilesHaveMD5HashMsg=MD5\u30CF\u30C3\u30B7\u30E5\u4ED8\u304D\u306E\u30D5\u30A1\u30A4\u30EB\u304C\u3042\u308A\u307E\u305B\u3093\u3002 -HashDbSearchPanel.errorText.noHashesAddedMsg=\u30A8\u30E9\u30FC\uFF1A\u30CF\u30C3\u30B7\u30E5\u304C\u8FFD\u52A0\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002 -HashDbSearchPanel.errorText.hashAlreadyAddedMsg=\u30A8\u30E9\u30FC\uFF1A\u30CF\u30C3\u30B7\u30E5\u304C\u65E2\u306B\u8FFD\u52A0\u3055\u308C\u3066\u3044\u307E\u3059\u3002 -HashDbSearchPanel.errorText.invalidMD5HashMsg=\u30A8\u30E9\u30FC\uFF1A\u6709\u52B9\u306AMD5\u30CF\u30C3\u30B7\u30E5\u3067\u306F\u3042\u308A\u307E\u305B\u3093\u3002 -HashDbSearchThread.progress.cancellingSearch={0}\uFF08\u30AD\u30E3\u30F3\u30BB\u30EB\u4E2D\u2026\uFF09 -HashDbSearchThread.name.searching=\u691C\u7D22\u4E2D -HashDbSearchThread.noMoreFilesWithMD5Msg=\u540C\u3058MD5\u30CF\u30C3\u30B7\u30E5\u4ED8\u304D\u306E\u30D5\u30A1\u30A4\u30EB\u306F\u4ED6\u306B\u3042\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002 -ModalNoButtons.indexingDbsTitle=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u4E2D -ModalNoButtons.indexingDbTitle=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u4E2D -ModalNoButtons.exitHashDbIndexingMsg=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306E\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u3092\u4E2D\u6B62\u3057\u307E\u3059\u3002\n\ -\u4F5C\u6210\u3055\u308C\u305F\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u306F\u5229\u7528\u4E0D\u53EF\u3068\u306A\u308A\u307E\u3059\u3002\u7D9A\u884C\u3059\u308B\u5834\u5408\u306F\n\ -\u30CF\u30C3\u30B7\u30E5\u30D5\u30A9\u30EB\u30C0\u5185\u306B\u3042\u308B\u3001\u5BFE\u5FDC\u3059\u308B-md5.idx \u30D5\u30A1\u30A4\u30EB\u3092\u524A\u9664\u3057\u3066\u4E0B\u3055\u3044\u3002\n\ -\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u3092\u4E2D\u6B62\u3057\u307E\u3059\u304B\uFF1F -ModalNoButtons.dlgTitle.unfinishedIndexing=\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u672A\u5B8C\u4E86 -ModalNoButtons.indexThis.currentlyIndexing1Db=\uFF11\u3064\u306E\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u4E2D -ModalNoButtons.indexThese.currentlyIndexing1OfNDbs=\uFF11\uFF0F {0}\u3064\u76EE\u3092\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u4E2D -ModalNoButtons.propChg.currentlyIndexingXofN={0}\uFF0F {1}\u3064\u76EE\u3092\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u5316\u4E2D -HashDbManager.duplicateHashSetNameExceptionMsg=\u30CF\u30C3\u30B7\u30E5\u30BB\u30C3\u30C8\u540D''{0}''\u306F\u65E2\u306B\u5225\u306E\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306B\u4F7F\u308F\u308C\u3066\u3044\u307E\u3059\u3002 -HashDbManager.hashDbDoesNotExistExceptionMsg=\u4E0B\u8A18\u3067\u306F\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F\n{0} -HashDbManager.hashDbFileExistsExceptionMsg=\u4E0B\u8A18\u306B\u306F\u65E2\u306B\u30D5\u30A1\u30A4\u30EB\u304C\u5B58\u5728\u3057\u307E\u3059\u3002\n{0} -HashDbManager.hashDbAlreadyAddedExceptionMsg=\u4E0B\u8A18\u306E\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\n{0}\n\u306F\u65E2\u306B\u4F5C\u6210\u307E\u305F\u306F\u30A4\u30F3\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u307E\u3059\u3002 -HashDbManager.illegalHashDbFileNameExtensionMsg=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30D5\u30A1\u30A4\u30EB\u540D\u306F.{0}\u306E\u62E1\u5F35\u5B50\u304C\u5FC5\u8981\u3067\u3059\u3002 -HashDbManager.moduleErr=\u30E2\u30B8\u30E5\u30FC\u30EB\u30A8\u30E9\u30FC -HashDbManager.knownBad.text=\u65E2\u77E5\u306E\u60AA\u8CEA -HashDbManager.known.text=\u65E2\u77E5 -HashDbManager.fileNameExtensionFilter.title=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30D5\u30A1\u30A4\u30EB -HashDbSearchAction.dlgMsg.title=MD5\u30CF\u30C3\u30B7\u30E5\u306B\u57FA\u3065\u3044\u305F\u30D5\u30A1\u30A4\u30EB\u691C\u7D22 -HashDbSearchAction.getName.text=\u30CF\u30C3\u30B7\u30E5\u691C\u7D22 -HashDbSearchPanel.dlgMsg.title=MD5\u30CF\u30C3\u30B7\u30E5\u306B\u57FA\u3065\u304F\u30D5\u30A1\u30A4\u30EB\u691C\u7D22 -AddContentToHashDbAction.singleSelectionName=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306B\u30D5\u30A1\u30A4\u30EB\u3092\u8FFD\u52A0 -AddContentToHashDbAction.multipleSelectionName=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306B\u30D5\u30A1\u30A4\u30EB\u3092\u8FFD\u52A0 -OptionsCategory_Name_HashDatabase=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9 -OptionsCategory_Keywords_HashDatabase=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9 -HashDbManager.ingestRunningExceptionMsg=\u51E6\u7406\u4E2D\uFF1B\u5B8C\u4E86\u3059\u308B\u307E\u3067\u3053\u306E\u30B5\u30FC\u30D3\u30B9\u306F\u5229\u7528\u3067\u304D\u307E\u305B\u3093\u3002 -ModalNoButtons.CURRENTDB_LABEL.text=\uFF08\u73FE\u5728\u306E\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\uFF09 -HashDbCreateDatabaseDialog.defaultFileName=\u30CF\u30C3\u30B7\u30E5\u30BB\u30C3\u30C8 -HashDbManager.saveErrorExceptionMsg=\u30CF\u30C3\u30B7\u30E5\u8A2D\u5B9A\u306E\u4FDD\u5B58\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F -AddContentToHashDbAction.addFilesToHashSet.files=\u30D5\u30A1\u30A4\u30EB -AddContentToHashDbAction.addFilesToHashSet.file=\u30D5\u30A1\u30A4\u30EB -HashDbManager.errCreatingIndex.title=\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u306E\u4F5C\u6210\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F -HashDbManager.errCreatingIndex.msg=\u4E0B\u8A18\u306E\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u306E\u4F5C\u6210\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\uFF1A {0} +AddContentToHashDbAction.ContentMenu.noHashDbsConfigd=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u305b\u3093 +AddContentToHashDbAction.ContentMenu.createDbItem=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u4f5c\u6210... +AddContentToHashDbAction.addFilesToHashSet.addToHashDbErr1.text=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30a8\u30e9\u30fc\u306b\u8ffd\u52a0 +AddContentToHashDbAction.addFilesToHashSet.addToHashDbErr2.text=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30a8\u30e9\u30fc\u306b\u8ffd\u52a0 +AddContentToHashDbAction.addFilesToHashSet.addToHashDbErr3.text=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30a8\u30e9\u30fc\u306b\u8ffd\u52a0 +AddContentToHashDbAction.addFilesToHashSet.unableToAddFileMsg=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306b{0}\u3092\u8ffd\u52a0\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +AddContentToHashDbAction.addFilesToHashSet.unableToAddFileSzMsg=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306b{0}\u3092\u8ffd\u52a0\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u30cf\u30c3\u30b7\u30e5\u5024\u304c\u8a08\u7b97\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002\u9069\u5207\u306a\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u8a2d\u5b9a\u3057\u3001\u5b9f\u884c\u3057\u3066\u4e0b\u3055\u3044\u3002 +HashDatabaseOptionsPanelController.moduleErr=\u30e2\u30b8\u30e5\u30fc\u30eb\u30a8\u30e9\u30fc +HashDatabaseOptionsPanelController.moduleErrMsg=HashDatabaseOptionsPanelController\u306e\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u3092\u78ba\u8a8d\u4e2d\u306b\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u30a8\u30e9\u30fc\u3092\u8d77\u3053\u3057\u307e\u3057\u305f\u3002\u3069\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u304b\u30ed\u30b0\u3067\u78ba\u8a8d\u3057\u3066\u4e0b\u3055\u3044\u3002\u4e00\u90e8\u306e\u30c7\u30fc\u30bf\u304c\u5b8c\u5168\u3067\u306a\u3044\u3053\u3068\u304c\u3042\u308a\u307e\u3059\u3002 +HashDbConfigPanel.noSelectionText=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u307e\u305b\u3093 +HashDbConfigPanel.errorGettingPathText=\u30d1\u30b9\u306e\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +HashDbConfigPanel.errorGettingIndexStatusText=\u30b9\u30c6\u30fc\u30bf\u30b9\u306e\u78ba\u8a8d\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +HashDbConfigPanel.setName.hashSetConfig=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u8a2d\u5b9a +HashDbConfigPanel.indexButtonText.index=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9 +HashDbConfigPanel.indexButtonText.indexing=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u4e2d +HashDbConfigPanel.indexStatusText.indexGen=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u3092\u4f5c\u6210\u4e2d\u3067\u3059 +HashDbConfigPanel.indexStatusText.indexOnly=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306e\u307f +HashDbConfigPanel.indexStatusText.indexed=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u6e08\u307f +HashDbConfigPanel.indexButtonText.reIndex=\u518d\u30a4\u30f3\u30c7\u30c3\u30af\u30b9 +HashDbConfigPanel.indexStatusText.noIndex=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u7121\u3057 +HashDbConfigPanel.dbsNotIndexedMsg=\u4e0b\u8a18\u306e\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306f\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u3057\u307e\u3059\u304b\uff1f\n {0} +HashDbConfigPanel.unindexedDbsMsg=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u3055\u308c\u3066\u3044\u306a\u3044\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9 +HashDbConfigPanel.allUnindexedDbsRmFromListMsg=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u3055\u308c\u3066\u3044\u306a\u3044\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306f\u30ea\u30b9\u30c8\u304b\u3089\u524a\u9664\u3055\u308c\u307e\u3059 +HashDbConfigPanel.nameColLbl=\u540d\u524d +HashDbConfigPanel.editingCellsNotSupportedMsg=\u30bb\u30eb\u306f\u7de8\u96c6\u4e0d\u53ef\u3067\u3059 +HashDbConfigPanel.deleteDbActionConfirmMsg=\u5168\u3066\u306e\u30b1\u30fc\u30b9\u306b\u304a\u3051\u308b\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u524a\u9664\u3057\u307e\u3059\u3002\u5b9f\u884c\u3057\u307e\u3059\u304b\uff1f +HashDbConfigPanel.deleteDbActionMsg=\u8a2d\u5b9a\u304b\u3089\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u524a\u9664 +HashDbCreateDatabaseDialog.createHashDbMsg=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u4f5c\u6210 +HashDbCreateDatabaseDialog.hashDbMustHaveFileExtensionMsg=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb\u306f .{0} \u306e\u62e1\u5f35\u5b50\u304c\u5fc5\u8981\u3067\u3059\u3002 +HashDbCreateDatabaseDialog.fileNameErr=\u30d5\u30a1\u30a4\u30eb\u540d\u30a8\u30e9\u30fc +HashDbCreateDatabaseDialog.fileNameAlreadyExistsMsg=\u540c\u540d\u306e\u30d5\u30a1\u30a4\u30eb\u304c\u65e2\u306b\u5b58\u5728\u3057\u307e\u3059\u3002\u5225\u306e\u30d5\u30a1\u30a4\u30eb\u540d\u3092\u8a2d\u5b9a\u3057\u3066\u4e0b\u3055\u3044\u3002 +HashDbCreateDatabaseDialog.fileExistsErr=\u30d5\u30a1\u30a4\u30eb\u304c\u65e2\u306b\u5b58\u5728\u3057\u3066\u3044\u308b\u30a8\u30e9\u30fc +HashDbCreateDatabaseDialog.mustEnterHashSetNameMsg=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u540d\u306e\u5165\u529b\u304c\u5fc5\u8981\u3067\u3059 +HashDbCreateDatabaseDialog.createHashDbErr=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u4f5c\u6210\u30a8\u30e9\u30fc +HashDbCreateDatabaseDialog.mustEnterHashDbPathMsg=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30d1\u30b9\u306e\u5165\u529b\u304c\u5fc5\u8981\u3067\u3059\u3002 +HashDbCreateDatabaseDialog.errMsg.hashDbCreationErr=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u4f5c\u6210\u30a8\u30e9\u30fc +HashDbCreateDatabaseDialog.cannotCreateFileAtLocMsg=\u6307\u5b9a\u3055\u308c\u305f\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3\u3067\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3002 +HashDbCreateDatabaseDialog.failedToCreateHashDbMsg=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u4f5c\u6210\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 +HashDbImportDatabaseDialog.importHashDbMsg=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u30a4\u30f3\u30dd\u30fc\u30c8 +HashDbImportDatabaseDialog.fileNameExtFilter.text=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb +HashDbImportDatabaseDialog.failedToGetDbPathMsg=\u9078\u629e\u3057\u305f\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30d1\u30b9\u306e\u5165\u624b\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 +HashDbImportDatabaseDialog.importHashDbErr=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30a4\u30f3\u30dd\u30fc\u30c8\u30a8\u30e9\u30fc +HashDbImportDatabaseDialog.mustSelectHashDbFilePathMsg=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb\u30d1\u30b9\u306e\u9078\u629e\u304c\u5fc5\u8981\u3067\u3059\u3002 +HashDbImportDatabaseDialog.hashDbDoesNotExistMsg=\u9078\u629e\u3055\u308c\u305f\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306f\u5b58\u5728\u3057\u307e\u305b\u3093\u3002 +HashDbImportDatabaseDialog.errorMessage.failedToOpenHashDbMsg={0}\u3067\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u958b\u304f\u306e\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 +HashDbIngestModule.moduleName=\u30cf\u30c3\u30b7\u30e5\u30eb\u30c3\u30af\u30a2\u30c3\u30d7 +HashDbIngestModule.moduleDescription=\u6a19\u6e96\u306eNSRL\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306a\u3069\u3001\u63d0\u4f9b\u3055\u308c\u305f\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u5229\u7528\u3057\u3066\u3001\u65e2\u77e5\u307e\u305f\u306f\u7591\u308f\u3057\u3044\u3082\u306e\u3092\u7279\u5b9a\u3057\u307e\u3059\u3002 +HashDbIngestModule.noKnownHashDbSetMsg=\u65e2\u77e5\u306e\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u5b58\u5728\u3057\u307e\u305b\u3093\u3002 +HashDbIngestModule.knownFileSearchWillNotExecuteWarn=\u65e2\u77e5\u306e\u30d5\u30a1\u30a4\u30eb\u691c\u7d22\u304c\u5b9f\u884c\u3055\u308c\u307e\u305b\u3093\u3002 +HashDbIngestModule.noKnownBadHashDbSetMsg=\u65e2\u77e5\u306e\u60aa\u8cea\u306a\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30bb\u30c3\u30c8\u306f\u3042\u308a\u307e\u305b\u3093\u3002 +HashDbConfigPanel.dbNotIndexedMsg=\u4e0b\u8a18\u306e\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306f\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u3057\u307e\u3059\u304b\uff1f\n{0} +HashDbIngestModule.knownBadFileSearchWillNotExecuteWarn=\u65e2\u77e5\u306e\u60aa\u8cea\u30d5\u30a1\u30a4\u30eb\u691c\u7d22\u306f\u5b9f\u884c\u3055\u308c\u307e\u305b\u3093\u3002 +HashDbIngestModule.fileReadErrorMsg=\u8aad\u307f\u8fbc\u307f\u30a8\u30e9\u30fc\uff1a {0} +HashDbIngestModule.calcHashValueErr={0}\u306e\u30cf\u30c3\u30b7\u30e5\u5024\u3092\u8a08\u7b97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +HashDbIngestModule.hashLookupErrorMsg=\u30cf\u30c3\u30b7\u30e5\u30eb\u30c3\u30af\u30a2\u30c3\u30d7\u30a8\u30e9\u30fc\uff1a {0} +HashDbIngestModule.settingKnownBadStateErr={0}\u306e\u30b9\u30c6\u30fc\u30bf\u30b9\u3092\u65e2\u77e5\u306e\u60aa\u8cea\u3068\u8a2d\u5b9a\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +HashDbIngestModule.lookingUpKnownBadHashValueErr={0}\u306e\u65e2\u77e5\u306e\u60aa\u8cea\u30cf\u30c3\u30b7\u30e5\u5024\u3092\u30eb\u30c3\u30af\u30a2\u30c3\u30d7\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +HashDbIngestModule.lookingUpKnownHashValueErr={0}\u306e\u65e2\u77e5\u306e\u60aa\u8cea\u30cf\u30c3\u30b7\u30e5\u5024\u3092\u30eb\u30c3\u30af\u30a2\u30c3\u30d7\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +HashDbIngestModule.postToBB.fileName=\u30d5\u30a1\u30a4\u30eb\u540d +HashDbIngestModule.postToBB.md5Hash=MD5\u30cf\u30c3\u30b7\u30e5 +HashDbIngestModule.postToBB.hashsetName=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u540d +HashDbIngestModule.postToBB.knownBadMsg=\u65e2\u77e5\u306e\u60aa\u8cea\: {0} +HashDbIngestModule.complete.knownBadsFound=\u767a\u898b\u3055\u308c\u305f\u65e2\u77e5\u306e\u60aa\u8cea\uff1a +HashDbIngestModule.complete.totalCalcTime=\u8a08\u7b97\u6642\u9593\u306e\u5408\u8a08 +HashDbIngestModule.complete.totalLookupTime=\u30eb\u30c3\u30af\u30a2\u30c3\u30d7\u6642\u9593\u306e\u5408\u8a08 +HashDbIngestModule.complete.databasesUsed=\u5229\u7528\u3057\u305f\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\uff1a +HashDbIngestModule.complete.hashLookupResults=\u30cf\u30c3\u30b7\u30e5\u30eb\u30c3\u30af\u30a2\u30c3\u30d7\u7d50\u679c +HashDbManager.moduleErrorListeningToUpdatesMsg=HashDbManager\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u3092\u78ba\u8a8d\u4e2d\u306b\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u30a8\u30e9\u30fc\u3092\u8d77\u3053\u3057\u307e\u3057\u305f\u3002\u3069\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u539f\u56e0\u306a\u306e\u304b\u3092\u30ed\u30b0\u3067\u78ba\u8a8d\u3057\u3066\u4e0b\u3055\u3044\u3002\u4e00\u90e8\u306e\u30c7\u30fc\u30bf\u304c\u5b8c\u5168\u3067\u306a\u3044\u3053\u3068\u304c\u3042\u308a\u307e\u3059\u3002 +HashDbManager.replacingDuplicateHashsetNameMsg=\u8907\u88fd\u306e\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u540d {0} \u304c\u898b\u3064\u304b\u308a\u307e\u3057\u305f\u3002\n {1}\u306b\u66f8\u304d\u63db\u3048\u307e\u3059\u3002 +HashDbManager.openHashDbErr=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u958b\u304f\u30a8\u30e9\u30fc +HashDbManager.unableToOpenHashDbMsg=\ {0} \u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u958b\u3051\u307e\u305b\u3093\u3002 +HashDbManager.savedBackupOfOldConfigMsg={0}\n\u53e4\u3044\u8a2d\u5b9a\u306e\u30d0\u30c3\u30af\u30a2\u30c3\u30d7\u30b3\u30d4\u30fc\u304c\u4e0b\u8a18\u306e\u901a\u308a\u4fdd\u5b58\u3055\u308c\u307e\u3057\u305f\u3002\n{1} +HashDbManager.baseMessage.updatedFormatHashDbConfig=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\u306e\u5f62\u5f0f\u304c\u66f4\u65b0\u3055\u308c\u307e\u3057\u305f\u3002 +HashDbManager.msgBoxTitle.confFileFmtChanged=\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\u5f62\u5f0f\u306e\u5909\u66f4\u5b8c\u4e86 +HashDbManager.dlgMsg.dbNotFoundAtLoc=\ {0} \u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306f\u4e0b\u8a18\u306e\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3\u306b\u3042\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002\n {1}\n \u30d5\u30a1\u30a4\u30eb\u3092\u691c\u7d22\u3057\u307e\u3059\u304b\uff1f +HashDbManager.dlgTitle.MissingDb=\u6b20\u843d\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9 +HashDbManager.progress.indexingHashSet=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u4e2d {0} +HashDbManager.dlgMsg.errorIndexingHashSet=\ {0} \u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u4e2d\u306e\u30a8\u30e9\u30fc +HashDbManager.hashDbIndexingErr=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u4e2d\u306e\u30a8\u30e9\u30fc +HashDbPanelSearchAction.actionName=MD5\u30cf\u30c3\u30b7\u30e5\u306b\u57fa\u3065\u304f\u30d5\u30a1\u30a4\u30eb\u691c\u7d22 +HashDbSearchAction.dlgMsg.noFilesHaveMD5Calculated=MD5\u30cf\u30c3\u30b7\u30e5\u304c\u8a08\u7b97\u3055\u308c\u3066\u3044\u308b\u30d5\u30a1\u30a4\u30eb\u304c\u3042\u308a\u307e\u305b\u3093\u3002\u307e\u305a\u306fHashDB\u3092\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3057\u3066\u4e0b\u3055\u3044\u3002 +HashDbSearchManager.MD5HashSearch=MD5\u30cf\u30c3\u30b7\u30e5\u691c\u7d22 +HashDbSearchManager.noResultsFoundMsg=\u4e00\u81f4\u3059\u308b\u3082\u306e\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +HashDbSearchPanel.titleText.ingestOngoing=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u4e2d\uff1b\u5b8c\u4e86\u3059\u308b\u307e\u3067\u3053\u306e\u30b5\u30fc\u30d3\u30b9\u306f\u5229\u7528\u3067\u304d\u307e\u305b\u3093\u3002 +HashDbSearchPanel.noFilesHaveMD5HashMsg=MD5\u30cf\u30c3\u30b7\u30e5\u4ed8\u304d\u306e\u30d5\u30a1\u30a4\u30eb\u304c\u3042\u308a\u307e\u305b\u3093\u3002 +HashDbSearchPanel.errorText.noHashesAddedMsg=\u30a8\u30e9\u30fc\uff1a\u30cf\u30c3\u30b7\u30e5\u304c\u8ffd\u52a0\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002 +HashDbSearchPanel.errorText.hashAlreadyAddedMsg=\u30a8\u30e9\u30fc\uff1a\u30cf\u30c3\u30b7\u30e5\u304c\u65e2\u306b\u8ffd\u52a0\u3055\u308c\u3066\u3044\u307e\u3059\u3002 +HashDbSearchPanel.errorText.invalidMD5HashMsg=\u30a8\u30e9\u30fc\uff1a\u6709\u52b9\u306aMD5\u30cf\u30c3\u30b7\u30e5\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002 +HashDbSearchThread.progress.cancellingSearch={0}\uff08\u30ad\u30e3\u30f3\u30bb\u30eb\u4e2d\u2026\uff09 +HashDbSearchThread.name.searching=\u691c\u7d22\u4e2d +HashDbSearchThread.noMoreFilesWithMD5Msg=\u540c\u3058MD5\u30cf\u30c3\u30b7\u30e5\u4ed8\u304d\u306e\u30d5\u30a1\u30a4\u30eb\u306f\u4ed6\u306b\u3042\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +ModalNoButtons.indexingDbsTitle=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u4e2d +ModalNoButtons.indexingDbTitle=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u4e2d +ModalNoButtons.exitHashDbIndexingMsg=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u3092\u4e2d\u6b62\u3057\u307e\u3059\u3002\n\ +\u4f5c\u6210\u3055\u308c\u305f\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306f\u5229\u7528\u4e0d\u53ef\u3068\u306a\u308a\u307e\u3059\u3002\u7d9a\u884c\u3059\u308b\u5834\u5408\u306f\n\ +\u30cf\u30c3\u30b7\u30e5\u30d5\u30a9\u30eb\u30c0\u5185\u306b\u3042\u308b\u3001\u5bfe\u5fdc\u3059\u308b-md5.idx \u30d5\u30a1\u30a4\u30eb\u3092\u524a\u9664\u3057\u3066\u4e0b\u3055\u3044\u3002\n\ +\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u3000\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u3092\u4e2d\u6b62\u3057\u307e\u3059\u304b\uff1f +ModalNoButtons.dlgTitle.unfinishedIndexing=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u672a\u5b8c\u4e86 +ModalNoButtons.indexThis.currentlyIndexing1Db=\uff11\u3064\u306e\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u4e2d +ModalNoButtons.indexThese.currentlyIndexing1OfNDbs=\uff11\uff0f {0}\u3064\u76ee\u3092\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u4e2d +ModalNoButtons.propChg.currentlyIndexingXofN={0}\uff0f {1}\u3064\u76ee\u3092\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5316\u4e2d +HashDbManager.duplicateHashSetNameExceptionMsg=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u540d''{0}''\u306f\u65e2\u306b\u5225\u306e\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306b\u4f7f\u308f\u308c\u3066\u3044\u307e\u3059\u3002 +HashDbManager.hashDbDoesNotExistExceptionMsg=\u4e0b\u8a18\u3067\u306f\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\n{0} +HashDbManager.hashDbFileExistsExceptionMsg=\u4e0b\u8a18\u306b\u306f\u65e2\u306b\u30d5\u30a1\u30a4\u30eb\u304c\u5b58\u5728\u3057\u307e\u3059\u3002\n{0} +HashDbManager.hashDbAlreadyAddedExceptionMsg=\u4e0b\u8a18\u306e\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\n{0}\n\u306f\u65e2\u306b\u4f5c\u6210\u307e\u305f\u306f\u30a4\u30f3\u30dd\u30fc\u30c8\u3055\u308c\u3066\u3044\u307e\u3059\u3002 +HashDbManager.illegalHashDbFileNameExtensionMsg=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb\u540d\u306f.{0}\u306e\u62e1\u5f35\u5b50\u304c\u5fc5\u8981\u3067\u3059\u3002 +HashDbManager.moduleErr=\u30e2\u30b8\u30e5\u30fc\u30eb\u30a8\u30e9\u30fc +HashDbManager.knownBad.text=\u65e2\u77e5\u306e\u60aa\u8cea +HashDbManager.known.text=\u65e2\u77e5 +HashDbManager.fileNameExtensionFilter.title=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb +HashDbSearchAction.dlgMsg.title=MD5\u30cf\u30c3\u30b7\u30e5\u306b\u57fa\u3065\u3044\u305f\u30d5\u30a1\u30a4\u30eb\u691c\u7d22 +HashDbSearchAction.getName.text=\u30cf\u30c3\u30b7\u30e5\u691c\u7d22 +HashDbSearchPanel.dlgMsg.title=MD5\u30cf\u30c3\u30b7\u30e5\u306b\u57fa\u3065\u304f\u30d5\u30a1\u30a4\u30eb\u691c\u7d22 +AddContentToHashDbAction.singleSelectionName=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306b\u30d5\u30a1\u30a4\u30eb\u3092\u8ffd\u52a0 +AddContentToHashDbAction.multipleSelectionName=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306b\u30d5\u30a1\u30a4\u30eb\u3092\u8ffd\u52a0 +OptionsCategory_Name_HashDatabase=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9 +OptionsCategory_Keywords_HashDatabase=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9 +HashDbManager.ingestRunningExceptionMsg=\u51e6\u7406\u4e2d\uff1b\u5b8c\u4e86\u3059\u308b\u307e\u3067\u3053\u306e\u30b5\u30fc\u30d3\u30b9\u306f\u5229\u7528\u3067\u304d\u307e\u305b\u3093\u3002 +ModalNoButtons.CURRENTDB_LABEL.text=\uff08\u73fe\u5728\u306e\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\uff09 +HashDbCreateDatabaseDialog.defaultFileName=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8 +HashDbManager.saveErrorExceptionMsg=\u30cf\u30c3\u30b7\u30e5\u8a2d\u5b9a\u306e\u4fdd\u5b58\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +AddContentToHashDbAction.addFilesToHashSet.files=\u30d5\u30a1\u30a4\u30eb +AddContentToHashDbAction.addFilesToHashSet.file=\u30d5\u30a1\u30a4\u30eb +HashDbManager.errCreatingIndex.title=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306e\u4f5c\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +HashDbManager.errCreatingIndex.msg=\u4e0b\u8a18\u306e\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306e\u4f5c\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a {0} -HashLookupSettingsPanel.optionsLabel.text=\u30AA\u30D7\u30B7\u30E7\u30F3 -HashLookupSettingsPanel.jButton3.text=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u30A4\u30F3\u30DD\u30FC\u30C8 -HashLookupSettingsPanel.indexPathLabelLabel.text=\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u30D1\u30B9\uFF1A -HashLookupSettingsPanel.createDatabaseButton.text=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u4F5C\u6210 -HashLookupSettingsPanel.jLabel6.text=\u30BF\u30A4\u30D7\uFF1A -HashLookupSettingsPanel.jLabel4.text=\u30ED\u30B1\u30FC\u30B7\u30E7\u30F3\uFF1A -HashLookupSettingsPanel.jLabel2.text=\u540D\u524D\uFF1A -HashLookupSettingsPanel.indexPathLabel.text=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304C\u9078\u629E\u3055\u308C\u3066\u3044\u307E\u305B\u3093 -HashLookupSettingsPanel.ingestWarningLabel.text=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u4E2D\u3067\u3059\u3002\u5B8C\u4E86\u3059\u308B\u307E\u3067\u4E00\u90E8\u306E\u8A2D\u5B9A\u306F\u5229\u7528\u3067\u304D\u307E\u305B\u3093\u3002 -HashLookupSettingsPanel.deleteDatabaseButton.text=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u524A\u9664 -HashLookupSettingsPanel.importDatabaseButton.text=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u30A4\u30F3\u30DD\u30FC\u30C8 -HashLookupSettingsPanel.hashDatabasesLabel.text=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\uFF1A -HashLookupSettingsPanel.nameLabel.text=\u30CF\u30C3\u30B7\u30E5\u30BB\u30C3\u30C8\u540D\uFF1A -HashLookupSettingsPanel.informationLabel.text=\u60C5\u5831 -HashLookupSettingsPanel.sendIngestMessagesCheckBox.text=\u30D2\u30C3\u30C8\u6BCE\u306B\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30A4\u30F3\u30DC\u30C3\u30AF\u30B9\u306B\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u9001\u308B -HashLookupSettingsPanel.hashDbLocationLabel.text=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304C\u9078\u629E\u3055\u308C\u3066\u3044\u307E\u305B\u3093 -HashLookupSettingsPanel.hashDbNameLabel.text=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304C\u9078\u629E\u3055\u308C\u3066\u3044\u307E\u305B\u3093 -HashLookupSettingsPanel.typeLabel.text=\u30BF\u30A4\u30D7\uFF1A -HashLookupSettingsPanel.locationLabel.text=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30D1\u30B9\uFF1A -HashLookupSettingsPanel.hashDbIndexStatusLabel.text=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304C\u9078\u629E\u3055\u308C\u3066\u3044\u307E\u305B\u3093 -HashLookupSettingsPanel.hashDbTypeLabel.text=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304C\u9078\u629E\u3055\u308C\u3066\u3044\u307E\u305B\u3093 -HashLookupSettingsPanel.indexButton.text=\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9 -HashLookupSettingsPanel.indexLabel.text=\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u30B9\u30C6\u30FC\u30BF\u30B9\uFF1A -HashLookupModuleSettingsPanel.alwaysCalcHashesCheckbox.text=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304C\u9078\u629E\u3055\u308C\u3066\u3044\u306A\u304F\u3066\u3082\u3001\u30CF\u30C3\u30B7\u30E5\u5024\u3092\u8A08\u7B97 -HashLookupModuleSettingsPanel.knownHashDbsLabel.text=\u5229\u7528\u3059\u308B\u65E2\u77E5\u306E\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u9078\u629E\uFF1A -HashLookupModuleSettingsPanel.knownBadHashDbsLabel.text=\u51E6\u7406\u306B\u5229\u7528\u3059\u308B\u65E2\u77E5\u306E\u60AA\u8CEA\u306A\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u9078\u629E\uFF1A -HashLookupModuleFactory.createFileIngestModule.exception.msg=\u8A2D\u5B9A\u3092\u884C\u3046\u70BA\u306E\u60F3\u5B9A\u3055\u308C\u308B\u5F15\u6570\u306Finstanceof HashLookupModuleSettings\u3067\u3059\u3002 -HashLookupModuleFactory.getIngestJobSettingsPanel.exception.msg=\u8A2D\u5B9A\u3092\u884C\u3046\u70BA\u306E\u60F3\u5B9A\u3055\u308C\u308B\u5F15\u6570\u306Finstanceof HashLookupModuleSettings\u3067\u3059\u3002 -HashLookupModuleSettingsPanel.alwaysCalcHashesCheckbox.toolTipText=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304C\u9078\u629E\u3055\u308C\u3066\u3044\u306A\u304F\u3066\u3082\u3001\u30CF\u30C3\u30B7\u30E5\u5024\u3092\u8A08\u7B97 -HashDbSearchPanel.hashTable.defaultModel.title.text=MD5\u30CF\u30C3\u30B7\u30E5 -AddContentToHashDbAction.addFilesToHashSet.unableToAddFileEmptyMsg=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306B{0}\u3092\u8FFD\u52A0\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u30D5\u30A1\u30A4\u30EB\u306B\u30B3\u30F3\u30C6\u30F3\u30C4\u304C\u3042\u308A\u307E\u305B\u3093\u3002 \ No newline at end of file +HashLookupSettingsPanel.optionsLabel.text=\u30aa\u30d7\u30b7\u30e7\u30f3 +HashLookupSettingsPanel.jButton3.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u30a4\u30f3\u30dd\u30fc\u30c8 +HashLookupSettingsPanel.indexPathLabelLabel.text=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u30d1\u30b9\uff1a +HashLookupSettingsPanel.createDatabaseButton.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u4f5c\u6210 +HashLookupSettingsPanel.jLabel6.text=\u30bf\u30a4\u30d7\uff1a +HashLookupSettingsPanel.jLabel4.text=\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3\uff1a +HashLookupSettingsPanel.jLabel2.text=\u540d\u524d\uff1a +HashLookupSettingsPanel.indexPathLabel.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u307e\u305b\u3093 +HashLookupSettingsPanel.ingestWarningLabel.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u4e2d\u3067\u3059\u3002\u5b8c\u4e86\u3059\u308b\u307e\u3067\u4e00\u90e8\u306e\u8a2d\u5b9a\u306f\u5229\u7528\u3067\u304d\u307e\u305b\u3093\u3002 +HashLookupSettingsPanel.deleteDatabaseButton.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u524a\u9664 +HashLookupSettingsPanel.importDatabaseButton.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u30a4\u30f3\u30dd\u30fc\u30c8 +HashLookupSettingsPanel.hashDatabasesLabel.text=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\uff1a +HashLookupSettingsPanel.nameLabel.text=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u540d\uff1a +HashLookupSettingsPanel.informationLabel.text=\u60c5\u5831 +HashLookupSettingsPanel.sendIngestMessagesCheckBox.text=\u30d2\u30c3\u30c8\u6bce\u306b\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30a4\u30f3\u30dc\u30c3\u30af\u30b9\u306b\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u9001\u308b +HashLookupSettingsPanel.hashDbLocationLabel.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u307e\u305b\u3093 +HashLookupSettingsPanel.hashDbNameLabel.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u307e\u305b\u3093 +HashLookupSettingsPanel.typeLabel.text=\u30bf\u30a4\u30d7\uff1a +HashLookupSettingsPanel.locationLabel.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30d1\u30b9\uff1a +HashLookupSettingsPanel.hashDbIndexStatusLabel.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u307e\u305b\u3093 +HashLookupSettingsPanel.hashDbTypeLabel.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u307e\u305b\u3093 +HashLookupSettingsPanel.indexButton.text=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9 +HashLookupSettingsPanel.indexLabel.text=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u30b9\u30c6\u30fc\u30bf\u30b9\uff1a +HashLookupModuleSettingsPanel.alwaysCalcHashesCheckbox.text=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u306a\u304f\u3066\u3082\u3001\u30cf\u30c3\u30b7\u30e5\u5024\u3092\u8a08\u7b97 +HashLookupModuleSettingsPanel.knownHashDbsLabel.text=\u5229\u7528\u3059\u308b\u65e2\u77e5\u306e\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u9078\u629e\uff1a +HashLookupModuleSettingsPanel.knownBadHashDbsLabel.text=\u51e6\u7406\u306b\u5229\u7528\u3059\u308b\u65e2\u77e5\u306e\u60aa\u8cea\u306a\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u9078\u629e\uff1a +HashLookupModuleFactory.createFileIngestModule.exception.msg=\u8a2d\u5b9a\u3092\u884c\u3046\u70ba\u306e\u60f3\u5b9a\u3055\u308c\u308b\u5f15\u6570\u306finstanceof HashLookupModuleSettings\u3067\u3059\u3002 +HashLookupModuleFactory.getIngestJobSettingsPanel.exception.msg=\u8a2d\u5b9a\u3092\u884c\u3046\u70ba\u306e\u60f3\u5b9a\u3055\u308c\u308b\u5f15\u6570\u306finstanceof HashLookupModuleSettings\u3067\u3059\u3002 +HashLookupModuleSettingsPanel.alwaysCalcHashesCheckbox.toolTipText=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u306a\u304f\u3066\u3082\u3001\u30cf\u30c3\u30b7\u30e5\u5024\u3092\u8a08\u7b97 +HashDbSearchPanel.hashTable.defaultModel.title.text=MD5\u30cf\u30c3\u30b7\u30e5 +AddContentToHashDbAction.addFilesToHashSet.unableToAddFileEmptyMsg=\u30cf\u30c3\u30b7\u30e5\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306b{0}\u3092\u8ffd\u52a0\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u30d5\u30a1\u30a4\u30eb\u306b\u30b3\u30f3\u30c6\u30f3\u30c4\u304c\u3042\u308a\u307e\u305b\u3093\u3002 diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.form b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.form index 3f08531859..d45778f1db 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.form @@ -127,6 +127,10 @@ + + + + @@ -204,7 +208,10 @@ - + + + + @@ -452,6 +459,17 @@ + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java index 3bc20c4da4..3db27037a4 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java @@ -34,6 +34,7 @@ import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableCellRenderer; +import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.corecomponents.OptionsPanel; @@ -121,6 +122,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan hashDbIndexStatusLabel.setForeground(Color.black); indexButton.setText(NbBundle.getMessage(this.getClass(), "HashDbConfigPanel.indexButtonText.index")); indexButton.setEnabled(false); + addHashesToDatabaseButton.setEnabled(false); // Update ingest options. sendIngestMessagesCheckBox.setSelected(false); @@ -157,6 +159,13 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan Logger.getLogger(HashLookupSettingsPanel.class.getName()).log(Level.SEVERE, "Error getting index path of " + db.getHashSetName() + " hash database", ex); //NON-NLS indexPathLabel.setText(ERROR_GETTING_PATH_TEXT); } + + try { + addHashesToDatabaseButton.setEnabled(!ingestIsRunning && db.isUpdateable()); + } catch (TskCoreException ex) { + Logger.getLogger(HashLookupSettingsPanel.class.getName()).log(Level.SEVERE, "Error identifying if the database is updateable.", ex); //NON-NLS + addHashesToDatabaseButton.setEnabled(false); + } // Update indexing components. try { @@ -481,6 +490,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan createDatabaseButton = new javax.swing.JButton(); indexPathLabelLabel = new javax.swing.JLabel(); indexPathLabel = new javax.swing.JLabel(); + addHashesToDatabaseButton = new javax.swing.JButton(); org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(HashLookupSettingsPanel.class, "HashLookupSettingsPanel.jLabel2.text")); // NOI18N @@ -590,6 +600,14 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan org.openide.awt.Mnemonics.setLocalizedText(indexPathLabel, org.openide.util.NbBundle.getMessage(HashLookupSettingsPanel.class, "HashLookupSettingsPanel.indexPathLabel.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(addHashesToDatabaseButton, org.openide.util.NbBundle.getMessage(HashLookupSettingsPanel.class, "HashLookupSettingsPanel.addHashesToDatabaseButton.text")); // NOI18N + addHashesToDatabaseButton.setEnabled(false); + addHashesToDatabaseButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + addHashesToDatabaseButtonActionPerformed(evt); + } + }); + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); jPanel1.setLayout(jPanel1Layout); jPanel1Layout.setHorizontalGroup( @@ -628,7 +646,10 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan .addComponent(hashDbTypeLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(hashDbLocationLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(indexPathLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(hashDbIndexStatusLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) + .addComponent(hashDbIndexStatusLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(addHashesToDatabaseButton) + .addGap(0, 0, Short.MAX_VALUE)))) .addGroup(jPanel1Layout.createSequentialGroup() .addComponent(nameLabel) .addGap(53, 53, 53) @@ -683,7 +704,9 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan .addComponent(indexLabel) .addComponent(hashDbIndexStatusLabel)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(indexButton) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(indexButton) + .addComponent(addHashesToDatabaseButton)) .addGap(18, 18, 18) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(optionsLabel) @@ -798,7 +821,15 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan ((HashSetTable) hashSetTable).selectRowByName(hashDb.getHashSetName()); } }//GEN-LAST:event_createDatabaseButtonActionPerformed + + private void addHashesToDatabaseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addHashesToDatabaseButtonActionPerformed + + HashDb hashDb = ((HashSetTable) hashSetTable).getSelection(); + new AddHashValuesToDatabaseDialog(hashDb); + }//GEN-LAST:event_addHashesToDatabaseButtonActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton addHashesToDatabaseButton; private javax.swing.JButton createDatabaseButton; private javax.swing.JButton deleteDatabaseButton; private javax.swing.JLabel hashDatabasesLabel; diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java index 18d41df409..e7d3e04da3 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java @@ -41,10 +41,10 @@ import java.util.Map; import java.util.TreeMap; import java.util.logging.Level; import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; -import org.openide.filesystems.FileUtil; import org.sleuthkit.autopsy.casemodule.services.Services; import org.sleuthkit.autopsy.casemodule.services.TagsManager; import org.sleuthkit.autopsy.coreutils.ImageUtils; @@ -52,13 +52,13 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.datamodel.ContentUtils.ExtractFscContentVisitor; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.datamodel.AbstractFile; -import org.sleuthkit.datamodel.Image; -import org.sleuthkit.datamodel.SleuthkitCase; -import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.ContentTag; +import org.sleuthkit.datamodel.Image; +import org.sleuthkit.datamodel.SleuthkitCase; +import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM; class ReportHTML implements TableReportModule { @@ -1109,7 +1109,7 @@ import org.sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM; } private String prepareThumbnail(AbstractFile file) { - File thumbFile = ImageUtils.getIconFile(file, ImageUtils.ICON_SIZE_MEDIUM); + File thumbFile = ImageUtils.getCachedThumbnailFile(file, ImageUtils.ICON_SIZE_MEDIUM); if (thumbFile.exists() == false) { return null; } diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportKML.java b/Core/src/org/sleuthkit/autopsy/report/ReportKML.java index 061329bf4a..b03af52227 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportKML.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportKML.java @@ -94,15 +94,11 @@ class ReportKML implements GeneralReportModule { progressPanel.setMaximumProgress(5); progressPanel.increment(); - // @@@ BC: I don't get why we do this in two passes. // Why not just print the coordinates as we find them and make some utility methods to do the printing? // Should pull out time values for all of these points and store in TimeSpan element try { - - BufferedWriter out = null; - try { - out = new BufferedWriter(new FileWriter(reportPath2)); + try (BufferedWriter out = new BufferedWriter(new FileWriter(reportPath2))) { double lat = 0; // temp latitude double lon = 0; //temp longitude @@ -110,7 +106,6 @@ class ReportKML implements GeneralReportModule { String geoPath = ""; // will hold values of images to put in kml String imageName = ""; - File f; for (BlackboardArtifact artifact : skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF)) { lat = 0; @@ -131,7 +126,7 @@ class ReportKML implements GeneralReportModule { if (lon != 0 && lat != 0) { aFile = artifact.getSleuthkitCase().getAbstractFileById(artifact.getObjectID()); - if(aFile != null){ + if (aFile != null) { extractedToPath = reportPath + aFile.getName(); geoPath = extractedToPath; f = new File(extractedToPath); @@ -150,7 +145,7 @@ class ReportKML implements GeneralReportModule { // lat lon path name } } - + for (BlackboardArtifact artifact : skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT)) { lat = 0; lon = 0; @@ -168,7 +163,7 @@ class ReportKML implements GeneralReportModule { out.write(lat + ";" + lon + "\n"); } } - + for (BlackboardArtifact artifact : skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_ROUTE)) { lat = 0; lon = 0; @@ -197,24 +192,23 @@ class ReportKML implements GeneralReportModule { location = attribute.getValueString(); } } - + // @@@ Should do something more fancy with these in KML and store them as a single point. String display = name; if (display.isEmpty()) display = location; - + if (lon != 0 && lat != 0) { out.write(NbBundle.getMessage(this.getClass(), "ReportKML.latLongStartPoint", lat, lon, display)); } if (destlat != 0 && destlon != 0) { out.write(NbBundle.getMessage(this.getClass(), "ReportKML.latLongEndPoint", destlat, destlon, - display)); + display)); } } - + out.flush(); - out.close(); - + progressPanel.increment(); /* * Step 1: generate XML stub @@ -236,7 +230,6 @@ class ReportKML implements GeneralReportModule { /* * Step 2: add in Style elements */ - // Style Element style = new Element("Style", ns); //NON-NLS style.setAttribute("id", "redIcon"); //NON-NLS @@ -266,72 +259,69 @@ class ReportKML implements GeneralReportModule { */ File file = new File(reportPath2); - BufferedReader reader; + try (BufferedReader reader = new BufferedReader(new FileReader(file))) { + String line = reader.readLine(); + while (line != null) { + String[] lineParts = line.split(";"); + if (lineParts.length > 1) { + String coordinates = lineParts[1].trim() + "," + lineParts[0].trim(); //lat,lon + // Placemark + Element placemark = new Element("Placemark", ns); //NON-NLS + document.addContent(placemark); - reader = new BufferedReader(new FileReader(file)); + if (lineParts.length == 4) { + // name + Element pmName = new Element("name", ns); //NON-NLS + pmName.setText(lineParts[3].trim()); + placemark.addContent(pmName); - String line = reader.readLine(); - while (line != null) { - String[] lineParts = line.split(";"); - if (lineParts.length > 1) { - String coordinates = lineParts[1].trim() + "," + lineParts[0].trim(); //lat,lon - // Placemark - Element placemark = new Element("Placemark", ns); //NON-NLS - document.addContent(placemark); + String savedPath = lineParts[2].trim(); + if (savedPath.isEmpty() == false) { + // Path + Element pmPath = new Element("Path", ns); //NON-NLS + pmPath.setText(savedPath); + placemark.addContent(pmPath); - if (lineParts.length == 4) { - // name - Element pmName = new Element("name", ns); //NON-NLS - pmName.setText(lineParts[3].trim()); - placemark.addContent(pmName); - - String savedPath = lineParts[2].trim(); - if (savedPath.isEmpty() == false) { - // Path - Element pmPath = new Element("Path", ns); //NON-NLS - pmPath.setText(savedPath); - placemark.addContent(pmPath); - - // description - Element pmDescription = new Element("description", ns); //NON-NLS - String xml = "

- + + + + + + + + + + + + + + + + + + + + diff --git a/CoreLibs/ivysettings.xml b/CoreLibs/ivysettings.xml index 342c6e237c..e3e086637b 100644 --- a/CoreLibs/ivysettings.xml +++ b/CoreLibs/ivysettings.xml @@ -1,11 +1,10 @@ - - - - - - - - + + + + + + + + diff --git a/CoreLibs/nbproject/project.properties b/CoreLibs/nbproject/project.properties index 8f133ac7fa..a44d89c6e1 100644 --- a/CoreLibs/nbproject/project.properties +++ b/CoreLibs/nbproject/project.properties @@ -3,6 +3,9 @@ file.reference.ant-1.8.2.jar=release/modules/ext/ant-1.8.2.jar file.reference.ant-launcher-1.8.2.jar=release/modules/ext/ant-launcher-1.8.2.jar file.reference.AppleJavaExtensions-1.4.jar=release/modules/ext/AppleJavaExtensions-1.4.jar file.reference.avalon-framework-4.1.5.jar=release/modules/ext/avalon-framework-4.1.5.jar +file.reference.common-image-3.1.1.jar=release/modules/ext/common-image-3.1.1.jar +file.reference.common-io-3.1.1.jar=release/modules/ext/common-io-3.1.1.jar +file.reference.common-lang-3.1.1.jar=release/modules/ext/common-lang-3.1.1.jar file.reference.commons-codec-1.5.jar=release/modules/ext/commons-codec-1.5.jar file.reference.commons-io-2.4.jar=release/modules/ext/commons-io-2.4.jar file.reference.commons-lang-2.6.jar=release/modules/ext/commons-lang-2.6.jar @@ -18,6 +21,20 @@ file.reference.geronimo-jms_1.1_spec-1.0.jar=release/modules/ext/geronimo-jms_1. file.reference.gson-1.4.jar=release/modules/ext/gson-1.4.jar file.reference.gstreamer-java-1.5.jar=release/modules/ext/gstreamer-java-1.5.jar file.reference.guava-11.0.2.jar=release/modules/ext/guava-11.0.2.jar +file.reference.imageio-bmp-3.1.1.jar=release/modules/ext/imageio-bmp-3.1.1.jar +file.reference.imageio-core-3.1.1.jar=release/modules/ext/imageio-core-3.1.1.jar +file.reference.imageio-icns-3.1.1.jar=release/modules/ext/imageio-icns-3.1.1.jar +file.reference.imageio-iff-3.1.1.jar=release/modules/ext/imageio-iff-3.1.1.jar +file.reference.imageio-jpeg-3.1.1.jar=release/modules/ext/imageio-jpeg-3.1.1.jar +file.reference.imageio-metadata-3.1.1.jar=release/modules/ext/imageio-metadata-3.1.1.jar +file.reference.imageio-pcx-3.1.1.jar=release/modules/ext/imageio-pcx-3.1.1.jar +file.reference.imageio-pict-3.1.1.jar=release/modules/ext/imageio-pict-3.1.1.jar +file.reference.imageio-pnm-3.1.1.jar=release/modules/ext/imageio-pnm-3.1.1.jar +file.reference.imageio-psd-3.1.1.jar=release/modules/ext/imageio-psd-3.1.1.jar +file.reference.imageio-sgi-3.1.1.jar=release/modules/ext/imageio-sgi-3.1.1.jar +file.reference.imageio-tga-3.1.1.jar=release/modules/ext/imageio-tga-3.1.1.jar +file.reference.imageio-thumbsdb-3.1.1.jar=release/modules/ext/imageio-thumbsdb-3.1.1.jar +file.reference.imageio-tiff-3.1.1.jar=release/modules/ext/imageio-tiff-3.1.1.jar file.reference.imgscalr-lib-4.2-javadoc.jar=release/modules/ext/imgscalr-lib-4.2-javadoc.jar file.reference.imgscalr-lib-4.2-sources.jar=release/modules/ext/imgscalr-lib-4.2-sources.jar file.reference.imgscalr-lib-4.2.jar=release/modules/ext/imgscalr-lib-4.2.jar diff --git a/CoreLibs/nbproject/project.xml b/CoreLibs/nbproject/project.xml index 9d02b18dc2..9f2244cf71 100644 --- a/CoreLibs/nbproject/project.xml +++ b/CoreLibs/nbproject/project.xml @@ -64,6 +64,41 @@ com.sun.mail.smtp com.sun.mail.util com.sun.mail.util.logging + com.twelvemonkeys.image + com.twelvemonkeys.imageio + com.twelvemonkeys.imageio.color + com.twelvemonkeys.imageio.metadata + com.twelvemonkeys.imageio.metadata.exif + com.twelvemonkeys.imageio.metadata.iptc + com.twelvemonkeys.imageio.metadata.jpeg + com.twelvemonkeys.imageio.metadata.psd + com.twelvemonkeys.imageio.metadata.xmp + com.twelvemonkeys.imageio.plugins.bmp + com.twelvemonkeys.imageio.plugins.dcx + com.twelvemonkeys.imageio.plugins.icns + com.twelvemonkeys.imageio.plugins.iff + com.twelvemonkeys.imageio.plugins.jpeg + com.twelvemonkeys.imageio.plugins.pcx + com.twelvemonkeys.imageio.plugins.pict + com.twelvemonkeys.imageio.plugins.pnm + com.twelvemonkeys.imageio.plugins.psd + com.twelvemonkeys.imageio.plugins.sgi + com.twelvemonkeys.imageio.plugins.tga + com.twelvemonkeys.imageio.plugins.thumbsdb + com.twelvemonkeys.imageio.plugins.tiff + com.twelvemonkeys.imageio.spi + com.twelvemonkeys.imageio.stream + com.twelvemonkeys.imageio.util + com.twelvemonkeys.io + com.twelvemonkeys.io.enc + com.twelvemonkeys.io.ole2 + com.twelvemonkeys.lang + com.twelvemonkeys.net + com.twelvemonkeys.util + com.twelvemonkeys.util.convert + com.twelvemonkeys.util.regex + com.twelvemonkeys.util.service + com.twelvemonkeys.xml javassist javassist.bytecode javassist.bytecode.analysis @@ -475,7 +510,6 @@ org.apache.xmlbeans.xml.stream.events org.apache.xmlbeans.xml.stream.utils org.apache.xmlcommons - org.controlsfx org.controlsfx.control org.controlsfx.control.action org.controlsfx.control.cell @@ -615,6 +649,18 @@ ext/logkit-1.0.1.jar release/modules/ext/logkit-1.0.1.jar + + ext/imageio-bmp-3.1.1.jar + release/modules/ext/imageio-bmp-3.1.1.jar + + + ext/imageio-pcx-3.1.1.jar + release/modules/ext/imageio-pcx-3.1.1.jar + + + ext/imageio-jpeg-3.1.1.jar + release/modules/ext/imageio-jpeg-3.1.1.jar + ext/imgscalr-lib-4.2-javadoc.jar release/modules/ext/imgscalr-lib-4.2-javadoc.jar @@ -675,6 +721,18 @@ ext/mail-1.4.3.jar release/modules/ext/mail-1.4.3.jar + + ext/imageio-tiff-3.1.1.jar + release/modules/ext/imageio-tiff-3.1.1.jar + + + ext/imageio-pnm-3.1.1.jar + release/modules/ext/imageio-pnm-3.1.1.jar + + + ext/common-lang-3.1.1.jar + release/modules/ext/common-lang-3.1.1.jar + ext/slf4j-api-1.6.1.jar release/modules/ext/slf4j-api-1.6.1.jar @@ -711,6 +769,10 @@ ext/poi-excelant-3.8.jar release/modules/ext/poi-excelant-3.8.jar + + ext/common-image-3.1.1.jar + release/modules/ext/common-image-3.1.1.jar + ext/log4j-1.2.17.jar release/modules/ext/log4j-1.2.17.jar @@ -743,6 +805,10 @@ ext/jfxtras-fxml-8.0-r1-javadoc.jar release/modules/ext/jfxtras-fxml-8.0-r1-javadoc.jar + + ext/common-io-3.1.1.jar + release/modules/ext/common-io-3.1.1.jar + ext/jfxtras-fxml-8.0-r1.jar release/modules/ext/jfxtras-fxml-8.0-r1.jar @@ -791,6 +857,10 @@ ext/commons-codec-1.5.jar release/modules/ext/commons-codec-1.5.jar + + ext/imageio-icns-3.1.1.jar + release/modules/ext/imageio-icns-3.1.1.jar + ext/javassist-3.12.1.GA.jar release/modules/ext/javassist-3.12.1.GA.jar @@ -799,14 +869,26 @@ ext/commons-logging-1.1.2.jar release/modules/ext/commons-logging-1.1.2.jar + + ext/imageio-psd-3.1.1.jar + release/modules/ext/imageio-psd-3.1.1.jar + ext/commons-io-2.4.jar release/modules/ext/commons-io-2.4.jar + + ext/imageio-sgi-3.1.1.jar + release/modules/ext/imageio-sgi-3.1.1.jar + ext/poi-3.8.jar release/modules/ext/poi-3.8.jar + + ext/imageio-thumbsdb-3.1.1.jar + release/modules/ext/imageio-thumbsdb-3.1.1.jar + ext/commons-lang3-3.0.jar release/modules/ext/commons-lang3-3.0.jar @@ -815,6 +897,18 @@ ext/jfxtras-common-8.0-r1-javadoc.jar release/modules/ext/jfxtras-common-8.0-r1-javadoc.jar + + ext/imageio-iff-3.1.1.jar + release/modules/ext/imageio-iff-3.1.1.jar + + + ext/imageio-tga-3.1.1.jar + release/modules/ext/imageio-tga-3.1.1.jar + + + ext/imageio-core-3.1.1.jar + release/modules/ext/imageio-core-3.1.1.jar + ext/javaee-api-5.0-2.jar release/modules/ext/javaee-api-5.0-2.jar @@ -823,10 +917,18 @@ ext/gstreamer-java-1.5.jar release/modules/ext/gstreamer-java-1.5.jar + + ext/imageio-metadata-3.1.1.jar + release/modules/ext/imageio-metadata-3.1.1.jar + ext/jfxtras-controls-8.0-r1-sources.jar release/modules/ext/jfxtras-controls-8.0-r1-sources.jar + + ext/imageio-pict-3.1.1.jar + release/modules/ext/imageio-pict-3.1.1.jar + ext/dom4j-1.6.1.jar release/modules/ext/dom4j-1.6.1.jar diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/FileTypeUtils.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/FileTypeUtils.java index 54589054ad..e9912e6b8e 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/FileTypeUtils.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/FileTypeUtils.java @@ -39,7 +39,10 @@ import org.sleuthkit.datamodel.TskCoreException; /** * Enum style singleton to provide utilities related to questions about a files - * type + * type, and wheather it should be supported in Image Gallery. + * + * TODO: refactor this to remove code that duplicates + * org.sleuthkit.autopsy.coreutils.ImageUtils */ public enum FileTypeUtils { @@ -87,6 +90,7 @@ public enum FileTypeUtils { * to be supported */ static { + ImageIO.scanForPlugins(); //add all extension ImageIO claims to support imageExtensions.addAll(Stream.of(ImageIO.getReaderFileSuffixes()) .map(String::toLowerCase) @@ -105,6 +109,8 @@ public enum FileTypeUtils { , "ai" //illustrator , "svg" //scalable vector graphics , "sn", "ras" //sun raster + , "ico" //windows icons + , "tga" //targa )); //add list of known video extensions @@ -118,10 +124,14 @@ public enum FileTypeUtils { videoMimeTypes.addAll(Arrays.asList("application/x-shockwave-flash")); supportedMimeTypes.addAll(videoMimeTypes); + supportedMimeTypes.addAll(Arrays.asList("application/x-123")); + //add list of mimetypes ImageIO claims to support supportedMimeTypes.addAll(Stream.of(ImageIO.getReaderMIMETypes()) .map(String::toLowerCase) .collect(Collectors.toList())); + + supportedMimeTypes.removeIf("application/octet-stream"::equals); //this is rearely usefull } /** @@ -161,9 +171,12 @@ public enum FileTypeUtils { */ public static boolean isDrawable(AbstractFile file) { return hasDrawableMimeType(file).orElseGet(() -> { - return FileTypeUtils.supportedExtensions.contains(file.getNameExtension()) - || ImageUtils.isJpegFileHeader(file) - || ImageUtils.isPngFileHeader(file); + final boolean contains = FileTypeUtils.supportedExtensions.contains(file.getNameExtension()); + final boolean jpegFileHeader = ImageUtils.isJpegFileHeader(file); + final boolean pngFileHeader = ImageUtils.isPngFileHeader(file); + return contains + || jpegFileHeader + || pngFileHeader; }); } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java index 5b8b59c05b..ade11f3165 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java @@ -453,15 +453,19 @@ public final class ImageGalleryController { * getOldValue has fileID getNewValue has * {@link Abstractfile} */ + AbstractFile file = (AbstractFile) evt.getNewValue(); + if (isListeningEnabled()) { - if (ImageGalleryModule.isDrawableAndNotKnown(file)) { - //this file should be included and we don't already know about it from hash sets (NSRL) - queueDBWorkerTask(new UpdateFileTask(file, db)); - } else if (FileTypeUtils.getAllSupportedExtensions().contains(file.getNameExtension())) { + if (file.isFile()) { + if (ImageGalleryModule.isDrawableAndNotKnown(file)) { + //this file should be included and we don't already know about it from hash sets (NSRL) + queueDBWorkerTask(new UpdateFileTask(file, db)); + } else if (FileTypeUtils.getAllSupportedExtensions().contains(file.getNameExtension())) { //doing this check results in fewer tasks queued up, and faster completion of db update - //this file would have gotten scooped up in initial grab, but actually we don't need it - queueDBWorkerTask(new RemoveFileTask(file, db)); + //this file would have gotten scooped up in initial grab, but actually we don't need it + queueDBWorkerTask(new RemoveFileTask(file, db)); + } } } else { //TODO: keep track of what we missed for later setStale(true); diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ThumbnailCache.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ThumbnailCache.java index fc1569bf08..0406bf7f79 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ThumbnailCache.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ThumbnailCache.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013 Basis Technology Corp. + * Copyright 2013-15 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -32,14 +32,17 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.function.Function; import java.util.logging.Level; +import javafx.beans.property.SimpleIntegerProperty; import javafx.embed.swing.SwingFXUtils; import javafx.scene.image.Image; +import javafx.scene.image.WritableImage; import javax.annotation.Nullable; import javax.imageio.ImageIO; import org.openide.util.Exceptions; import org.sleuthkit.autopsy.coreutils.ImageUtils; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; +import org.sleuthkit.autopsy.imagegallery.gui.Toolbar; import org.sleuthkit.datamodel.ReadContentInputStream; import org.sleuthkit.datamodel.TskCoreException; @@ -53,8 +56,6 @@ public enum ThumbnailCache { instance; - /** save thumbnails to disk as this format */ - private static final String FORMAT = "png"; private static final int MAX_THUMBNAIL_SIZE = 300; private static final Logger LOGGER = Logger.getLogger(ThumbnailCache.class.getName()); @@ -71,6 +72,9 @@ public enum ThumbnailCache { return instance; } + /** currently desired icon size. is bound in {@link Toolbar} */ + public final SimpleIntegerProperty iconSize = new SimpleIntegerProperty(200); + /** * Clear out the cache between cases */ @@ -122,39 +126,43 @@ public enum ThumbnailCache { return Optional.of(new Image(new BufferedInputStream(new ReadContentInputStream(file.getAbstractFile())), MAX_THUMBNAIL_SIZE, MAX_THUMBNAIL_SIZE, true, true)); } - Image thumbnail; + BufferedImage thumbnail = getCacheFile(file).map(new Function() { + @Override + public BufferedImage apply(File cachFile) { + if (cachFile.exists()) { + // If a thumbnail file is already saved locally, load it + try { + BufferedImage read = ImageIO.read(cachFile); + + if (read.getWidth() < MAX_THUMBNAIL_SIZE) { + return read; - try { - thumbnail = getCacheFile(file.getId()).map(new Function() { - @Override - public Image apply(File cachFile) { - if (cachFile.exists()) { - // If a thumbnail file is already saved locally, load it - try { - BufferedImage read = ImageIO.read(cachFile); - if (read.getWidth() < MAX_THUMBNAIL_SIZE) { - return SwingFXUtils.toFXImage(read, null); - } - } catch (MalformedURLException ex) { - LOGGER.log(Level.WARNING, "Unable to parse cache file path.."); - } catch (IOException ex) { - Exceptions.printStackTrace(ex); } + } catch (MalformedURLException ex) { + LOGGER.log(Level.WARNING, "Unable to parse cache file path.."); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); } - return null; } - }).orElse(null); + return null; + } + }).orElseGet(() -> { + return (BufferedImage) ImageUtils.getThumbnail(file.getAbstractFile(), MAX_THUMBNAIL_SIZE); + }); - } catch (IllegalStateException e) { - LOGGER.log(Level.WARNING, "can't load icon when no case is open"); - return Optional.empty(); +// } catch (IllegalStateException e) { +// LOGGER.log(Level.WARNING, "can't load icon when no case is open"); +// return Optional.empty(); +// } + WritableImage jfxthumbnail; + if (thumbnail == ImageUtils.getDefaultThumbnail()) { + // if we go the default icon, ignore it + jfxthumbnail = null; + } else { + jfxthumbnail = SwingFXUtils.toFXImage(thumbnail, null); } - if (thumbnail == null) { //if we failed to load the icon, try to generate it - thumbnail = generateAndSaveThumbnail(file); - } - - return Optional.ofNullable(thumbnail); //return icon, or null if generation failed + return Optional.ofNullable(jfxthumbnail); //return icon, or null if generation failed } /** @@ -163,12 +171,12 @@ public enum ThumbnailCache { * @param id the obj id of the file to get a cache file for * * @return a Optional containing a File to store the cahced icon in or an - * empty optional if there was a - * problem. + * empty optional if there was a problem. */ - private static Optional getCacheFile(long id) { + private static Optional getCacheFile(DrawableFile file) { try { - return Optional.of(ImageUtils.getFile(id)); + return Optional.of(ImageUtils.getCachedThumbnailFile(file.getAbstractFile(), MAX_THUMBNAIL_SIZE)); + } catch (IllegalStateException e) { LOGGER.log(Level.WARNING, "Failed to create cache file.{0}", e.getLocalizedMessage()); return Optional.empty(); @@ -188,4 +196,5 @@ public enum ThumbnailCache { final BufferedImage thumbnail = (BufferedImage) ImageUtils.getIcon(file.getAbstractFile(), MAX_THUMBNAIL_SIZE); return (thumbnail == ImageUtils.getDefaultIcon()) ? null : SwingFXUtils.toFXImage(thumbnail, null); } + } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/ImageFile.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/ImageFile.java index b77955c828..4ccde39649 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/ImageFile.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/ImageFile.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013 Basis Technology Corp. + * Copyright 2013-15 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -34,12 +34,16 @@ import org.sleuthkit.datamodel.ReadContentInputStream; /** * ImageGallery data model object that represents an image file. It is a * wrapper(/decorator?/adapter?) around {@link AbstractFile} and provides - * methods to get an icon sized and a full sized {@link Image}. - * - * + * methods to get an thumbnail sized and a full sized {@link Image}. */ public class ImageFile extends DrawableFile { + private static final Logger LOGGER = Logger.getLogger(ImageFile.class.getName()); + + static { + ImageIO.scanForPlugins(); + } + ImageFile(T f, Boolean analyzed) { super(f, analyzed); @@ -53,20 +57,12 @@ public class ImageFile extends DrawableFile { @Override public Image getFullSizeImage() { Image image = (imageRef != null) ? imageRef.get() : null; - - if (image == null) { - try (BufferedInputStream readContentInputStream = new BufferedInputStream(new ReadContentInputStream(this.getAbstractFile()))) { - image = new Image(readContentInputStream); - } catch (IOException ex) { - Logger.getLogger(ImageFile.class.getName()).log(Level.WARNING, "unable to read file with JavaFX" + getName()); - } - } - if (image == null || image.errorProperty().get()) { + if (image == null || image.isError()) { try (BufferedInputStream readContentInputStream = new BufferedInputStream(new ReadContentInputStream(this.getAbstractFile()))) { BufferedImage read = ImageIO.read(readContentInputStream); image = SwingFXUtils.toFXImage(read, null); } catch (IOException | NullPointerException ex) { - Logger.getLogger(ImageFile.class.getName()).log(Level.WARNING, "unable to read file with Swing" + getName()); + LOGGER.log(Level.WARNING, "unable to read file " + getName()); return null; } } @@ -74,6 +70,11 @@ public class ImageFile extends DrawableFile { return image; } + @Override + public boolean isDisplayable() { + Image thumbnail = getThumbnail(); + return Objects.nonNull(thumbnail) && thumbnail.errorProperty().get() == false; + } @Override Double getWidth() { diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/VideoFile.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/VideoFile.java index 95985bbc4c..ec9d595e02 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/VideoFile.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/VideoFile.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013 Basis Technology Corp. + * Copyright 2013-15 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.imagegallery.datamodel; +import com.google.common.io.Files; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; @@ -60,8 +61,8 @@ public class VideoFile extends DrawableFile { Image image = (imageRef != null) ? imageRef.get() : null; if (image == null) { - final BufferedImage bufferedImage = (BufferedImage) ImageUtils.getIcon(getAbstractFile(), 1024); - imageRef = new SoftReference<>((bufferedImage == ImageUtils.getDefaultIcon()) ? null : SwingFXUtils.toFXImage(bufferedImage, null)); + final BufferedImage bufferedImage = (BufferedImage) ImageUtils.getThumbnail(getAbstractFile(), 1024); + imageRef = new SoftReference<>((bufferedImage == ImageUtils.getDefaultThumbnail()) ? null : SwingFXUtils.toFXImage(bufferedImage, null)); } return image; @@ -79,10 +80,13 @@ public class VideoFile extends DrawableFile { final File cacheFile = VideoUtils.getTempVideoFile(this.getAbstractFile()); if (cacheFile.exists() == false || cacheFile.length() < getAbstractFile().getSize()) { + + Files.createParentDirs(cacheFile); ProgressHandle progressHandle = ProgressHandleFactory.createHandle("writing temporary file to disk"); progressHandle.start(100); ContentUtils.writeToFile(this.getAbstractFile(), cacheFile, progressHandle, null, true); progressHandle.finish(); + } media = new Media(Paths.get(cacheFile.getAbsolutePath()).toUri().toString()); diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableTileBase.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableTileBase.java index 7a32507c35..18270282a2 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableTileBase.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableTileBase.java @@ -315,10 +315,10 @@ public abstract class DrawableTileBase extends DrawableUIBase { Platform.runLater(() -> { fileTypeImageView.setManaged(isVideo); - hashHitImageView.setManaged(hasHashSetHits); - undisplayableImageView.setManaged(isUndisplayable); fileTypeImageView.setVisible(isVideo); + hashHitImageView.setManaged(hasHashSetHits); hashHitImageView.setVisible(hasHashSetHits); + undisplayableImageView.setManaged(isUndisplayable); undisplayableImageView.setVisible(isUndisplayable); nameLabel.setText(text); nameLabel.setTooltip(new Tooltip(text));