diff --git a/Core/src/org/sleuthkit/autopsy/apputils/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/apputils/Bundle_ja.properties new file mode 100644 index 0000000000..72a20f2a27 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/apputils/Bundle_ja.properties @@ -0,0 +1,4 @@ +#Mon Jun 14 12:23:19 UTC 2021 +CTL_ResetWindowsAction=\u30a6\u30a3\u30f3\u30c9\u30a6\u3092\u30ea\u30bb\u30c3\u30c8 +ResetWindowAction.confirm.text=\u30d7\u30ed\u30b0\u30e9\u30e0\u3092\u9589\u3058\u3066\u518d\u8d77\u52d5\u3057\u3001\u30a6\u30a3\u30f3\u30c9\u30a6\u306e\u4f4d\u7f6e\u3092\u30ea\u30bb\u30c3\u30c8\u3057\u307e\u3059\u3002\n\n\u3059\u3079\u3066\u306e\u30a6\u30a3\u30f3\u30c9\u30a6\u306e\u4f4d\u7f6e\u3092\u30ea\u30bb\u30c3\u30c8\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b\uff1f +ResetWindowAction.confirm.title=\u30a6\u30a3\u30f3\u30c9\u30a6\u3092\u30ea\u30bb\u30c3\u30c8 diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties index f85f5c62d2..ccdc57d555 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties @@ -1,4 +1,4 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Mon Jun 14 12:23:19 UTC 2021 AddImageAction.ingestConfig.ongoingIngest.msg=\u5225\u306e\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3067\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u304c\u9032\u884c\u4e2d\u3067\u3059\u3002\u65b0\u898f\u30bd\u30fc\u30b9\u3092\u4eca\u8ffd\u52a0\u3059\u308b\u3068\u3001\u73fe\u5728\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u306e\u51e6\u7406\u304c\u9045\u304f\u306a\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002
\u7d9a\u884c\u3057\u3066\u65b0\u898f\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u4eca\u3059\u3050\u8ffd\u52a0\u3057\u307e\u3059\u304b? AddImageAction.ingestConfig.ongoingIngest.title=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u304c\u9032\u884c\u4e2d\u3067\u3059 AddImageAction.wizard.title=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u8ffd\u52a0 @@ -25,10 +25,17 @@ AddImageWizardChooseDataSourceVisual.getName.text=\u30c7\u30fc\u30bf\u30bd\u30fc AddImageWizardIngestConfigPanel.CANCEL_BUTTON.text=\u53d6\u308a\u6d88\u3057 AddImageWizardIngestConfigPanel.dsProcDone.errs.text=*\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306e\u8ffd\u52a0\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 AddImageWizardIngestConfigPanel.dsProcDone.noErrs.text=*\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u8ffd\u52a0\u3057\u307e\u3057\u305f\u3002 -AddImageWizardIngestConfigPanel.name.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u69cb\u6210 -AddImageWizardIngestConfigVisual.getName.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u69cb\u6210 +AddImageWizardIngestConfigPanel.name.text=\u53d6\u8fbc\u307f\u306e\u69cb\u6210 +AddImageWizardIngestConfigVisual.getName.text=\u53d6\u8fbc\u307f\u306e\u69cb\u6210 AddImageWizardIterator.stepXofN=\u624b\u9806 {0} / {1} AddImageWizardSelectDspVisual.multiUserWarning.text=\u3053\u306e\u30bf\u30a4\u30d7\u306e\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u30d7\u30ed\u30bb\u30c3\u30b5\u30fc\u306f\u30de\u30eb\u30c1\u30e6\u30fc\u30b6\u30fc\u30e2\u30fc\u30c9\u3067\u5229\u7528\u3067\u304d\u307e\u305b\u3093\u3002 +AddImageWizardSelectHostPanel_title=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u8ffd\u52a0\u3059\u308b\u30db\u30b9\u30c8\u306e\u9078\u629e +AddImageWizardSelectHostVisual.generateNewRadio.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u540d\u306b\u57fa\u3065\u3044\u3066\u65b0\u30db\u30b9\u30c8\u540d\u306e\u4f5c\u6210 +AddImageWizardSelectHostVisual.hostDescription.text=\u30db\u30b9\u30c8\u306f\u3001\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3084\u305d\u306e\u4ed6\u306e\u30c7\u30fc\u30bf\u3092\u6574\u7406\u3059\u308b\u305f\u3081\u306b\u4f7f\u7528\u3055\u308c\u307e\u3059\u3002 +AddImageWizardSelectHostVisual.specifyNewHostRadio.text=\u65b0\u30db\u30b9\u30c8\u540d\u306e\u6307\u5b9a +AddImageWizardSelectHostVisual.useExistingHostRadio.text=\u65e2\u5b58\u306e\u30db\u30b9\u30c8\u306e\u4f7f\u7528 +AddImageWizardSelectHostVisual_getValidationMessage_noHostSelected=\u65e2\u5b58\u306e\u30db\u30b9\u30c8\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +AddImageWizardSelectHostVisual_title=\u30db\u30b9\u30c8\u306e\u9078\u629e AddLocalFilesTask.localFileAdd.progress.text=\u6b21\u3092\u8ffd\u52a0\u4e2d\u3067\u3059\: {0}/{1} CTL_AddImage=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u8ffd\u52a0 CTL_AddImageButton=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u8ffd\u52a0 @@ -86,6 +93,8 @@ Case.exceptionMessage.failedToReadMetadata=\u30b1\u30fc\u30b9\u30e1\u30bf\u30c7\ Case.exceptionMessage.metadataUpdateError=\u30b1\u30fc\u30b9\u30e1\u30bf\u30c7\u30fc\u30bf\u3092\u66f4\u65b0\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f Case.exceptionMessage.unsupportedSchemaVersionMessage=\u30b5\u30dd\u30fc\u30c8\u3055\u308c\u3066\u3044\u306a\u3044\u30b1\u30fc\u30b9\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30b9\u30ad\u30fc\u30de\u30d0\u30fc\u30b8\u30e7\u30f3\u3067\u3059\:\n{0}\u3002 Case.getCurCase.exception.noneOpen=\u73fe\u5728\u306e\u30b1\u30fc\u30b9\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3002\u30b1\u30fc\u30b9\u304c\u958b\u304b\u308c\u3066\u3044\u307e\u305b\u3093\! +Case.lockingException.couldNotAcquireExclusiveLock=\u30b1\u30fc\u30b9\u306e\u6392\u4ed6\u30ed\u30c3\u30af\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +Case.lockingException.couldNotAcquireSharedLock=\u30b1\u30fc\u30b9\u306e\u5171\u6709\u30ed\u30c3\u30af\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 Case.metaDataFileCorrupt.exception.msg=\u30b1\u30fc\u30b9\u30e1\u30bf\u30c7\u30fc\u30bf\u30d5\u30a1\u30a4\u30eb(.aut)\u304c\u7834\u640d\u3057\u3066\u3044\u307e\u3059\u3002 Case.open.exception.multiUserCaseNotEnabled=\u30de\u30eb\u30c1\u30e6\u30fc\u30b6\u30fc\u30b1\u30fc\u30b9\u304c\u6709\u52b9\u3067\u306a\u3044\u5834\u5408\u306f\u30de\u30eb\u30c1\u30e6\u30fc\u30b6\u30fc\u30b1\u30fc\u30b9\u3092\u958b\u3051\u307e\u305b\u3093\u3002[\u30c4\u30fc\u30eb]\u3001[\u30aa\u30d7\u30b7\u30e7\u30f3]\u3001[\u30de\u30eb\u30c1\u30e6\u30fc\u30b6\u30fc] \u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\u3002 Case.open.msgDlg.updated.msg=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30b9\u30ad\u30fc\u30de\u3092\u66f4\u65b0\u3057\u307e\u3057\u305f\u3002\n\u6b21\u306e\u30d1\u30b9\u3092\u6301\u3064\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30d0\u30c3\u30af\u30a2\u30c3\u30d7\u30b3\u30d4\u30fc\u3092\u4f5c\u6210\u3057\u307e\u3057\u305f\:\n {0} @@ -384,7 +393,7 @@ ReviewModeCasePanel.StatusIconHeaderText=\u30b9\u30c6\u30fc\u30bf\u30b9 ReviewModeCasePanel.cannotOpenCase=\u30b1\u30fc\u30b9\u3092\u958b\u3051\u307e\u305b\u3093 ReviewModeCasePanel.caseIsLocked=\u30b7\u30f3\u30b0\u30eb\u30e6\u30fc\u30b6\u30fc\u304c\u30ed\u30c3\u30af\u3055\u308c\u3066\u3044\u307e\u3059\u3002 ReviewModeCasePanel.casePathNotFound=\u30b1\u30fc\u30b9\u30d1\u30b9\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093 -SelectDataSourceProcessorPanel.name.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306e\u30bf\u30a4\u30d7\u3092\u9078\u629e\u3057\u3066\u8ffd\u52a0 +SelectDataSourceProcessorPanel.name.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u30bf\u30a4\u30d7\u306e\u9078\u629e SingleUserCaseConverter.AlreadyMultiUser=\u30b1\u30fc\u30b9\u306f\u3059\u3067\u306b\u30de\u30eb\u30c1\u30e6\u30fc\u30b6\u30fc\u3067\u3059\! SingleUserCaseConverter.BadDatabaseFileName=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb\u306f\u5b58\u5728\u3057\u307e\u305b\u3093\! SingleUserCaseConverter.CanNotOpenDatabase=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u958b\u3051\u307e\u305b\u3093 diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/IngestJobInfoPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/IngestJobInfoPanel.java index 5fe65783b0..5161a544ca 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/IngestJobInfoPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/IngestJobInfoPanel.java @@ -26,8 +26,10 @@ import java.util.Date; import java.util.EnumSet; import java.util.List; import java.util.Set; +import java.util.concurrent.ExecutionException; import java.util.logging.Level; import javax.swing.JOptionPane; +import javax.swing.SwingWorker; import javax.swing.event.ListSelectionEvent; import javax.swing.table.AbstractTableModel; import org.openide.util.NbBundle.Messages; @@ -51,12 +53,13 @@ public final class IngestJobInfoPanel extends javax.swing.JPanel { private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.STARTED, IngestManager.IngestJobEvent.CANCELLED, IngestManager.IngestJobEvent.COMPLETED); private static final Set CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.CURRENT_CASE); private static final int EXTRA_ROW_HEIGHT = 4; - private List ingestJobs; + private final List ingestJobs = new ArrayList<>(); private final List ingestJobsForSelectedDataSource = new ArrayList<>(); private IngestJobTableModel ingestJobTableModel = new IngestJobTableModel(); private IngestModuleTableModel ingestModuleTableModel = new IngestModuleTableModel(null); private final DateFormat datetimeFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); private DataSource selectedDataSource; + private static SwingWorker refreshWorker = null; /** * Creates new form IngestJobInfoPanel @@ -76,19 +79,19 @@ public final class IngestJobInfoPanel extends javax.swing.JPanel { this.ingestModuleTable.setModel(this.ingestModuleTableModel); }); - IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST , (PropertyChangeEvent evt) -> { + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, (PropertyChangeEvent evt) -> { if (evt.getPropertyName().equals(IngestManager.IngestJobEvent.STARTED.toString()) || evt.getPropertyName().equals(IngestManager.IngestJobEvent.CANCELLED.toString()) || evt.getPropertyName().equals(IngestManager.IngestJobEvent.COMPLETED.toString())) { refresh(); } }); - + Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, (PropertyChangeEvent evt) -> { if (!(evt instanceof AutopsyEvent) || (((AutopsyEvent) evt).getSourceType() != AutopsyEvent.SourceType.LOCAL)) { return; } - + // Check whether we have a case open or case close event. if ((CURRENT_CASE == Case.Events.valueOf(evt.getPropertyName()))) { if (evt.getNewValue() != null) { @@ -102,7 +105,7 @@ public final class IngestJobInfoPanel extends javax.swing.JPanel { }); ingestJobTable.setRowHeight(ingestJobTable.getRowHeight() + EXTRA_ROW_HEIGHT); ingestModuleTable.setRowHeight(ingestModuleTable.getRowHeight() + EXTRA_ROW_HEIGHT); - + } /** @@ -133,27 +136,51 @@ public final class IngestJobInfoPanel extends javax.swing.JPanel { * Get the updated complete list of ingest jobs. */ private void refresh() { - try { - if (Case.isCaseOpen()) { // Note - this will generally return true when handling a case close event - SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase(); - this.ingestJobs = skCase.getIngestJobs(); - setDataSource(selectedDataSource); - } else { - this.ingestJobs = new ArrayList<>(); - setDataSource(null); - } - - } catch (TskCoreException | NoCurrentCaseException ex) { - logger.log(Level.SEVERE, "Failed to load ingest jobs.", ex); - JOptionPane.showMessageDialog(this, Bundle.IngestJobInfoPanel_loadIngestJob_error_text(), Bundle.IngestJobInfoPanel_loadIngestJob_error_title(), JOptionPane.ERROR_MESSAGE); + if (refreshWorker != null && !refreshWorker.isDone()) { + refreshWorker.cancel(true); } + refreshWorker = new SwingWorker() { + + @Override + protected Boolean doInBackground() throws Exception { + ingestJobs.clear(); + try { + if (Case.isCaseOpen()) { // Note - this will generally return true when handling a case close event + SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase(); + ingestJobs.addAll(skCase.getIngestJobs()); + setDataSource(selectedDataSource); + } else { + setDataSource(null); + } + return true; + } catch (TskCoreException | NoCurrentCaseException ex) { + logger.log(Level.SEVERE, "Failed to load ingest jobs.", ex); + return false; + } + } + + @Override + protected void done() { + try { + if (!get()) { + JOptionPane.showMessageDialog(IngestJobInfoPanel.this, Bundle.IngestJobInfoPanel_loadIngestJob_error_text(), Bundle.IngestJobInfoPanel_loadIngestJob_error_title(), JOptionPane.ERROR_MESSAGE); + } + } catch (InterruptedException | ExecutionException ex) { + logger.log(Level.WARNING, "Error getting results from Ingest Job Info Panel's refresh worker", ex); + } + } + }; + refreshWorker.execute(); } - + /** * Reset the panel. */ private void reset() { - this.ingestJobs = new ArrayList<>(); + if (refreshWorker != null) { + refreshWorker.cancel(true); + } + this.ingestJobs.clear(); setDataSource(null); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java index deaa0d1ca8..34f26eb1ac 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java @@ -130,8 +130,7 @@ public class FileManager implements Closeable { * @throws TskCoreException */ public List findFilesExactName(long parentId, String name) throws TskCoreException{ - String whereClause = "name = '%s'"; - return caseDb.findAllFilesInFolderWhere(parentId, String.format(whereClause, name)); + return caseDb.getFileManager().findFilesExactName(parentId, name); } /** diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle_ja.properties index 68dfcf62be..94ea2014f5 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle_ja.properties @@ -1,54 +1,49 @@ -DataContentViewerOtherCases.caseDetailsDialog.noCaseNameError=\u30a8\u30e9\u30fc -DataContentViewerOtherCases.caseDetailsDialog.noDetails=\u3053\u306e\u30b1\u30fc\u30b9\u306e\u8a73\u7d30\u306f\u3042\u308a\u307e\u305b\u3093\u3002 -DataContentViewerOtherCases.caseDetailsDialog.noDetailsReference=\u30b0\u30ed\u30fc\u30d0\u30eb\u30ec\u30d5\u30a1\u30ec\u30f3\u30b9\u30d7\u30ed\u30d1\u30c6\u30a3\u306e\u30b1\u30fc\u30b9\u8a73\u7d30\u306f\u3042\u308a\u307e\u305b\u3093\u3002 -DataContentViewerOtherCases.caseDetailsDialog.notSelected=\u884c\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u307e\u305b\u3093 -# {0} - \u5171\u6709\u6027\u306e\u5272\u5408 -# {1} - \u76f8\u95a2\u5206\u6790\u30bf\u30a4\u30d7 -# {2} - \u76f8\u95a2\u5206\u6790\u5024 -DataContentViewerOtherCases.correlatedArtifacts.byType=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306e {0}% \u306b {2} \u304c\u3042\u308a\u307e\u3059(\u30bf\u30a4\u30d7: {1})\n -DataContentViewerOtherCases.correlatedArtifacts.failed=\u983b\u5ea6\u306e\u8a73\u7d30\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 -DataContentViewerOtherCases.correlatedArtifacts.isEmpty=\u76f8\u95a2\u5206\u6790\u3059\u308b\u305f\u3081\u306e\u30d5\u30a1\u30a4\u30eb\u3084\u904e\u53bb\u306e\u691c\u7d22\u7d50\u679c\u304c\u3042\u308a\u307e\u305b\u3093\u3002 -DataContentViewerOtherCases.correlatedArtifacts.title=\u5c5e\u6027\u983b\u5ea6 -DataContentViewerOtherCases.dataSources.header.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u540d -DataContentViewerOtherCases.earliestCaseNotAvailable=\ \u6709\u52b9\u306b\u306a\u3063\u3066\u3044\u307e\u305b\u3093\u3002 -DataContentViewerOtherCases.foundIn.text=%d \u306e\u30b1\u30fc\u30b9\u3068 %d \u306e\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u5185\u306b %d \u306e\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u304c\u898b\u3064\u304b\u308a\u307e\u3057\u305f\u3002 -DataContentViewerOtherCases.noOpenCase.errMsg=\u958b\u3044\u3066\u3044\u308b\u30b1\u30fc\u30b9\u306f\u3042\u308a\u307e\u305b\u3093\u3002 -DataContentViewerOtherCases.table.noArtifacts=\u9805\u76ee\u306b\u691c\u7d22\u306b\u5229\u7528\u3067\u304d\u308b\u5c5e\u6027\u306f\u3042\u308a\u307e\u305b\u3093\u3002 -DataContentViewerOtherCases.table.noResultsFound=\u8a72\u5f53\u3059\u308b\u7d50\u679c\u304c\u3042\u308a\u307e\u305b\u3093\u3002 +#Mon Jun 14 12:23:19 UTC 2021 DataContentViewerOtherCases.table.toolTip.text=\u5217\u540d\u3092\u30af\u30ea\u30c3\u30af\u3057\u3066\u30bd\u30fc\u30c8\u3057\u307e\u3059\u3002\u30c6\u30fc\u30d6\u30eb\u3092\u53f3\u30af\u30ea\u30c3\u30af\u3057\u3066\u3055\u3089\u306a\u308b\u30aa\u30d7\u30b7\u30e7\u30f3\u3092\u8868\u793a\u3057\u307e\u3059\u3002 DataContentViewerOtherCases.title=\u305d\u306e\u4ed6\u306e\u767a\u751f DataContentViewerOtherCases.toolTip=\u305d\u306e\u4ed6\u306e\u767a\u751f\u304b\u3089\u9078\u629e\u3057\u305f\u30d5\u30a1\u30a4\u30eb/\u904e\u53bb\u306e\u691c\u7d22\u7d50\u679c\u306e\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u3092\u8868\u793a\u3057\u307e\u3059\u3002 -DataContentViewerOtherCasesModel.csvHeader.attribute=\u4e00\u81f4\u3057\u305f\u5c5e\u6027 -DataContentViewerOtherCasesModel.csvHeader.case=\u30b1\u30fc\u30b9 -DataContentViewerOtherCasesModel.csvHeader.comment=\u30b3\u30e1\u30f3\u30c8 -DataContentViewerOtherCasesModel.csvHeader.dataSource=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9 -DataContentViewerOtherCasesModel.csvHeader.device=\u30c7\u30d0\u30a4\u30b9 -DataContentViewerOtherCasesModel.csvHeader.known=\u65e2\u77e5 -DataContentViewerOtherCasesModel.csvHeader.path=\u30d1\u30b9 -DataContentViewerOtherCasesModel.csvHeader.value=\u5c5e\u6027\u5024 -OccurrencePanel.caseCreatedDateLabel.text=\u4f5c\u6210\u65e5: +OccurrencePanel.caseCreatedDateLabel.text=\u4f5c\u6210\u65e5\: OccurrencePanel.caseDetails.text=\u30b1\u30fc\u30b9\u8a73\u7d30 -OccurrencePanel.caseNameLabel.text=\u540d\u524d: +OccurrencePanel.caseNameLabel.text=\u540d\u524d\: OccurrencePanel.commonProperties.text=\u5171\u901a\u306e\u30d7\u30ed\u30d1\u30c6\u30a3 -OccurrencePanel.commonPropertyCommentLabel.text=\u30b3\u30e1\u30f3\u30c8: -OccurrencePanel.commonPropertyKnownStatusLabel.text=\u65e2\u77e5\u306e\u30b9\u30c6\u30fc\u30bf\u30b9: -OccurrencePanel.commonPropertyTypeLabel.text=\u30bf\u30a4\u30d7: -OccurrencePanel.commonPropertyValueLabel.text=\u5024: +OccurrencePanel.commonPropertyCommentLabel.text=\u30b3\u30e1\u30f3\u30c8\: +OccurrencePanel.commonPropertyKnownStatusLabel.text=\u65e2\u77e5\u306e\u30b9\u30c6\u30fc\u30bf\u30b9\: +OccurrencePanel.commonPropertyTypeLabel.text=\u30bf\u30a4\u30d7\: +OccurrencePanel.commonPropertyValueLabel.text=\u5024\: OccurrencePanel.dataSourceDetails.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u8a73\u7d30 -OccurrencePanel.dataSourceNameLabel.text=\u540d\u524d: +OccurrencePanel.dataSourceNameLabel.text=\u540d\u524d\: OccurrencePanel.fileDetails.text=\u30d5\u30a1\u30a4\u30eb\u8a73\u7d30 -OccurrencePanel.filePathLabel.text=\u30d5\u30a1\u30a4\u30eb\u30d1\u30b9: +OccurrencePanel.filePathLabel.text=\u30d5\u30a1\u30a4\u30eb\u30d1\u30b9\: OtherOccurrencesCasesTableModel.case=\u30b1\u30fc\u30b9 OtherOccurrencesCasesTableModel.noData=\u30c7\u30fc\u30bf\u304c\u3042\u308a\u307e\u305b\u3093\u3002 OtherOccurrencesDataSourcesTableModel.dataSourceName=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u540d OtherOccurrencesDataSourcesTableModel.noData=\u30c7\u30fc\u30bf\u304c\u3042\u308a\u307e\u305b\u3093\u3002 OtherOccurrencesFilesTableModel.fileName=\u30d5\u30a1\u30a4\u30eb\u540d OtherOccurrencesFilesTableModel.noData=\u30c7\u30fc\u30bf\u304c\u3042\u308a\u307e\u305b\u3093\u3002 -OtherOccurrencesPanel.filesTable.toolTipText=\u5217\u540d\u3092\u30af\u30ea\u30c3\u30af\u3057\u3066\u30bd\u30fc\u30c8\u3057\u307e\u3059\u3002\u30c6\u30fc\u30d6\u30eb\u3092\u53f3\u30af\u30ea\u30c3\u30af\u3057\u3066\u3055\u3089\u306a\u308b\u30aa\u30d7\u30b7\u30e7\u30f3\u3092\u8868\u793a\u3057\u307e\u3059\u3002 -OtherOccurrencesPanel.earliestCaseLabel.toolTipText= -OtherOccurrencesPanel.earliestCaseLabel.text=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ec\u30dd\u30b8\u30c8\u30ea\u30fc\u958b\u59cb\u65e5: -OtherOccurrencesPanel.earliestCaseDate.text=\u6700\u3082\u53e4\u3044\u30b1\u30fc\u30b9\u65e5\u4ed8 -OtherOccurrencesPanel.foundInLabel.text= +OtherOccurrencesPanel.caseDetailsDialog.noCaseNameError=\u30a8\u30e9\u30fc +OtherOccurrencesPanel.caseDetailsDialog.noDetails=\u3053\u306e\u30b1\u30fc\u30b9\u306e\u8a73\u7d30\u306f\u3042\u308a\u307e\u305b\u3093\u3002 +OtherOccurrencesPanel.caseDetailsDialog.noDetailsReference=\u30b0\u30ed\u30fc\u30d0\u30eb\u53c2\u7167\u30d7\u30ed\u30d1\u30c6\u30a3\u306e\u30b1\u30fc\u30b9\u306e\u8a73\u7d30\u306f\u3042\u308a\u307e\u305b\u3093\u3002 +OtherOccurrencesPanel.caseDetailsDialog.notSelected=\u884c\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u307e\u305b\u3093 +OtherOccurrencesPanel.correlatedArtifacts.byType=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306e{0}\uff05\u306b{2}\u304c\u3042\u308a\u307e\u3059\uff08\u30bf\u30a4\u30d7\uff1a{1}\uff09 +OtherOccurrencesPanel.correlatedArtifacts.failed=\u983b\u5ea6\u306e\u8a73\u7d30\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +OtherOccurrencesPanel.correlatedArtifacts.isEmpty=\u95a2\u9023\u4ed8\u3051\u308b\u30d5\u30a1\u30a4\u30eb\u3084\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u306f\u3042\u308a\u307e\u305b\u3093\u3002 +OtherOccurrencesPanel.correlatedArtifacts.title=\u30a2\u30c8\u30ea\u30d3\u30e5\u30fc\u30c8\u306e\u983b\u5ea6 +OtherOccurrencesPanel.csvHeader.attribute=\u4e00\u81f4\u3057\u305f\u30a2\u30c8\u30ea\u30d3\u30e5\u30fc\u30c8 +OtherOccurrencesPanel.csvHeader.case=\u30b1\u30fc\u30b9 +OtherOccurrencesPanel.csvHeader.comment=\u30b3\u30e1\u30f3\u30c8 +OtherOccurrencesPanel.csvHeader.dataSource=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9 +OtherOccurrencesPanel.csvHeader.device=\u30c7\u30d0\u30a4\u30b9 +OtherOccurrencesPanel.csvHeader.known=\u65e2\u77e5 +OtherOccurrencesPanel.csvHeader.path=\u30d1\u30b9 +OtherOccurrencesPanel.csvHeader.value=\u30a2\u30c8\u30ea\u30d3\u30e5\u30fc\u30c8\u5024 +OtherOccurrencesPanel.earliestCaseDate.text=\u30b1\u30fc\u30b9\u306e\u6700\u521d\u306e\u65e5\u4ed8 +OtherOccurrencesPanel.earliestCaseLabel.text=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u306e\u958b\u59cb\u65e5\uff1a +OtherOccurrencesPanel.earliestCaseNotAvailable=\u6709\u52b9\u306b\u306a\u3063\u3066\u3044\u307e\u305b\u3093\u3002 +OtherOccurrencesPanel.exportToCSVMenuItem.text=\u305d\u306e\u4ed6\u306e\u3059\u3079\u3066\u306e\u767a\u751f\u3092CSV\u306b\u30a8\u30af\u30b9\u30dd\u30fc\u30c8 +OtherOccurrencesPanel.filesTable.toolTipText=\u4e26\u3079\u66ff\u3048\u306f\u5217\u540d\u3092\u30af\u30ea\u30c3\u30af\u3002 \u305d\u306e\u4ed6\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u306f\u3001\u30c6\u30fc\u30d6\u30eb\u3092\u53f3\u30af\u30ea\u30c3\u30af\u3002 +OtherOccurrencesPanel.foundIn.text=\uff05d\u30b1\u30fc\u30b9\u3068\uff05d\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3067\uff05d\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u304c\u898b\u3064\u304b\u308a\u307e\u3057\u305f\u3002 +OtherOccurrencesPanel.noOpenCase.errMsg=\u30aa\u30fc\u30d7\u30f3\u30b1\u30fc\u30b9\u306f\u3042\u308a\u307e\u305b\u3093\u3002 +OtherOccurrencesPanel.showCaseDetailsMenuItem.text=\u30b1\u30fc\u30b9\u306e\u8a73\u7d30\u3092\u8868\u793a OtherOccurrencesPanel.showCommonalityMenuItem.text=\u983b\u5ea6\u3092\u8868\u793a -OtherOccurrencesPanel.showCaseDetailsMenuItem.text=\u30b1\u30fc\u30b9\u8a73\u7d30\u3092\u8868\u793a -OtherOccurrencesPanel.exportToCSVMenuItem.text=\u305d\u306e\u4ed6\u3059\u3079\u3066\u306e\u767a\u751f\u3092CSV\u306b\u30a8\u30af\u30b9\u30dd\u30fc\u30c8 +OtherOccurrencesPanel.table.noArtifacts=\u30a2\u30a4\u30c6\u30e0\u306b\u306f\u3001\u691c\u7d22\u3059\u308b\u30a2\u30c8\u30ea\u30d3\u30e5\u30fc\u30c8\u304c\u3042\u308a\u307e\u305b\u3093\u3002 +OtherOccurrencesPanel.table.noResultsFound=\u7d50\u679c\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002 diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle_ja.properties index f92bd670f4..07a447b55c 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle_ja.properties @@ -1,4 +1,4 @@ -#Tue Aug 18 18:09:20 UTC 2020 +#Mon Jun 14 12:23:19 UTC 2021 AddNewOrganizationDialog.addNewOrg.msg=\u65b0\u898f\u7d44\u7e54\u3092\u8ffd\u52a0 AddNewOrganizationDialog.bnCancel.text=\u53d6\u308a\u6d88\u3057 AddNewOrganizationDialog.bnOK.text=OK @@ -93,9 +93,9 @@ GlobalSettingsPanel.manageOrganizationButton.text=\u7d44\u7e54\u3092\u7ba1\u7406 GlobalSettingsPanel.onMultiUserChange.disabledMu.description=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u30fc\u306f\u30ed\u30fc\u30ab\u30ebSQLite\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3068\u3057\u3066\u518d\u69cb\u6210\u3055\u308c\u307e\u3059 GlobalSettingsPanel.onMultiUserChange.disabledMu.description2=[PostgreSQL\u306e\u69cb\u6210]\u3092\u62bc\u3057\u3066\u3001PostgreSQL\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306b\u5909\u66f4\u3057\u307e\u3059\u3002 GlobalSettingsPanel.onMultiUserChange.disabledMu.title=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u30fc\u306e\u5909\u66f4\u304c\u5fc5\u8981\u3067\u3059 -GlobalSettingsPanel.onMultiUserChange.enable.description=\u3053\u306ePostgreSQL\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u4f7f\u7528\u3059\u308b\u3088\u3046\u306b\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u30fc\u3092\u66f4\u65b0\u3057\u307e\u3059\u304b\uff1f -GlobalSettingsPanel.onMultiUserChange.enable.description2=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u30fc\u306b\u306f\u904e\u53bb\u306e\u30b1\u30fc\u30b9\u304b\u3089\u306e\u30cf\u30c3\u30b7\u30e5\u5024\u3068\u30a2\u30ab\u30a6\u30f3\u30c8\u304c\u4fdd\u5b58\u3055\u308c\u307e\u3059\u3002 -GlobalSettingsPanel.onMultiUserChange.enable.title=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u30fc\u3067\u4f7f\u7528\u3057\u307e\u3059\u304b\uff1f +GlobalSettingsPanel.onMultiUserChange.enable.description=\u3053\u306ePostgreSQL\u30b5\u30fc\u30d0\u30fc\u3092\u4f7f\u7528\u3059\u308b\u3088\u3046\u306b\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u3092\u66f4\u65b0\u3057\u307e\u3059\u304b\uff1f +GlobalSettingsPanel.onMultiUserChange.enable.description2=\u65e2\u5b58\u306eSQLite\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u306e\u30c7\u30fc\u30bf\u306f\u65b0\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306b\u8ee2\u9001\u3055\u308c\u307e\u305b\u3093\u3002 +GlobalSettingsPanel.onMultiUserChange.enable.title=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea GlobalSettingsPanel.organizationPanel.border.title=\u7d44\u7e54 GlobalSettingsPanel.organizationTextArea.text=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ec\u30dd\u30b8\u30c8\u30ea\u30fc\u5185\u3067\u7d44\u7e54\u60c5\u5831\u3092\u8ffd\u8de1\u3067\u304d\u307e\u3059\u3002 GlobalSettingsPanel.pnCorrelationProperties.border.title=\u76f8\u95a2\u5206\u6790\u30d7\u30ed\u30d1\u30c6\u30a3 diff --git a/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InstanceCountNode.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InstanceCountNode.java index 5be8f8bae2..628bec9291 100644 --- a/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InstanceCountNode.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InstanceCountNode.java @@ -2,7 +2,7 @@ * * Autopsy Forensic Browser * - * Copyright 2018-2019 Basis Technology Corp. + * Copyright 2018-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -60,7 +60,7 @@ public final class InstanceCountNode extends DisplayableItemNode { "InstanceCountNode.displayName=Exists in %s data sources (%s)" }) public InstanceCountNode(int instanceCount, CommonAttributeValueList attributeValues, CorrelationAttributeInstance.Type type) { - super(Children.create(new CommonAttributeValueNodeFactory(attributeValues.getMetadataList(), type), false)); + super(Children.create(new CommonAttributeValueNodeFactory(attributeValues.getMetadataList(), type), true)); this.type = type; this.instanceCount = instanceCount; this.attributeValues = attributeValues; diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/communications/relationships/Bundle_ja.properties index b02216ee0e..28885c1191 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/Bundle_ja.properties @@ -1,4 +1,4 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Mon Jun 14 12:23:19 UTC 2021 ContactDetailsPane.nameLabel.text=\u30d7\u30ec\u30fc\u30b9\u30db\u30eb\u30c0\u30fc ContactNode_Email=\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9 ContactNode_Home_Number=\u81ea\u5b85\u96fb\u8a71\u756a\u53f7 @@ -64,7 +64,7 @@ SummaryViewer_CentralRepository_Message=<\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u3 SummaryViewer_Creation_Date_Title=\u4f5c\u6210\u65e5 SummaryViewer_Fetching_References=<\u30d5\u30a1\u30a4\u30eb\u53c2\u7167\u306e\u53d6\u5f97> SummaryViewer_FileRefNameColumn_Title=\u30d1\u30b9 -SummaryViewer_Persona_Message=<\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u304c\u30da\u30eb\u30bd\u30ca\u3092\u8868\u793a\u53ef\u80fd\u306b\u3059\u308b> +SummaryViewer_Persona_CR_Message=<\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u304c\u30da\u30eb\u30bd\u30ca\u3092\u8868\u793a\u3067\u304d\u308b\u3088\u3046\u306b\u3059\u308b> SummaryViewer_Select_account_for_persona=<\u30da\u30eb\u30bd\u30ca\u3092\u8868\u793a\u3059\u308b\u306b\u306f\u3001\u30a2\u30ab\u30a6\u30f3\u30c8\u30921\u3064\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044> SummaryViewer_TabTitle=\u30b5\u30de\u30ea\u30fc SummeryViewer_FileRef_Message=<\u30a2\u30ab\u30a6\u30f3\u30c8\u30921\u3064\u9078\u629e\u3057\u3066\u30d5\u30a1\u30a4\u30eb\u30ec\u30d5\u30a1\u30ec\u30f3\u30b9\u3092\u8868\u793a> diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogViewer.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogViewer.java index 21d7deb8bd..f2b99df0dd 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogViewer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 Basis Technology Corp. + * Copyright 2019-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -119,9 +119,9 @@ final class CallLogViewer extends javax.swing.JPanel implements RelationshipsVie updateOutlineViewPanel(); } }); - + TableColumn column = outline.getColumnModel().getColumn(2); - column.setCellRenderer(new NodeTableCellRenderer() ); + column.setCellRenderer(new NodeTableCellRenderer()); } @@ -164,7 +164,9 @@ final class CallLogViewer extends javax.swing.JPanel implements RelationshipsVie @Override public void setSelectionInfo(SelectionInfo info) { + callLogDataViewer.setNode(null); nodeFactory.refresh(info); + } @Override @@ -229,7 +231,7 @@ final class CallLogViewer extends javax.swing.JPanel implements RelationshipsVie } } - + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JScrollPane bottomScrollPane; private org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel outlineViewPanel; diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/ContactsChildNodeFactory.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/ContactsChildNodeFactory.java index 28666c8fdd..ab980ee101 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/ContactsChildNodeFactory.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/ContactsChildNodeFactory.java @@ -35,7 +35,8 @@ import org.sleuthkit.datamodel.TskCoreException; /** * ChildFactory for ContactNodes. */ -final class ContactsChildNodeFactory extends ChildFactory{ +final class ContactsChildNodeFactory extends ChildFactory { + private static final Logger logger = Logger.getLogger(ContactsChildNodeFactory.class.getName()); private SelectionInfo selectionInfo; @@ -47,12 +48,13 @@ final class ContactsChildNodeFactory extends ChildFactory{ * accounts */ ContactsChildNodeFactory(SelectionInfo selectionInfo) { - this.selectionInfo = selectionInfo; + this.selectionInfo = selectionInfo; } - + /** - * Updates the current instance of selectionInfo and calls the refresh method. - * + * Updates the current instance of selectionInfo and calls the refresh + * method. + * * @param selectionInfo New instance of the currently selected accounts */ public void refresh(SelectionInfo selectionInfo) { @@ -63,13 +65,15 @@ final class ContactsChildNodeFactory extends ChildFactory{ /** * Creates a list of Keys (BlackboardArtifact) for only contacts of the * currently selected accounts + * * @param list List of BlackboardArtifact to populate + * * @return True on success */ @Override protected boolean createKeys(List list) { - - if(selectionInfo == null) { + + if (selectionInfo == null) { return true; } @@ -80,7 +84,7 @@ final class ContactsChildNodeFactory extends ChildFactory{ logger.log(Level.SEVERE, "Failed to load relationship sources.", ex); //NON-NLS return false; } - + relationshipSources.stream().filter((content) -> (content instanceof BlackboardArtifact)).forEachOrdered((content) -> { BlackboardArtifact bba = (BlackboardArtifact) content; diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/ContactsViewer.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/ContactsViewer.java index 1d11b3ef6d..6366d4e517 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/ContactsViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/ContactsViewer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 Basis Technology Corp. + * Copyright 2019-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -35,7 +35,6 @@ import org.openide.nodes.NodeAdapter; import org.openide.nodes.NodeMemberEvent; import org.openide.util.Lookup; import org.openide.util.NbBundle; -import org.openide.util.lookup.ServiceProvider; import org.sleuthkit.autopsy.communications.ModifiableProxyLookup; import org.sleuthkit.autopsy.corecomponents.TableFilterNode; import org.sleuthkit.autopsy.directorytree.DataResultFilterNode; @@ -126,6 +125,7 @@ final class ContactsViewer extends JPanel implements RelationshipsViewer { @Override public void setSelectionInfo(SelectionInfo info) { + contactPane.setNode(null); nodeFactory.refresh(info); } diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/MediaViewer.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/MediaViewer.java index daffdafb81..63988b200d 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/MediaViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/MediaViewer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 Basis Technology Corp. + * Copyright 2019-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -99,18 +99,19 @@ final class MediaViewer extends JPanel implements RelationshipsViewer, ExplorerM public void setSelectionInfo(SelectionInfo info) { Set relationshipSources; Set artifactList = new HashSet<>(); + contentViewer.setNode(null); + if (info != null) { + try { + relationshipSources = info.getRelationshipSources(); - try { - relationshipSources = info.getRelationshipSources(); + relationshipSources.stream().filter((content) -> (content instanceof BlackboardArtifact)).forEachOrdered((content) -> { + artifactList.add((BlackboardArtifact) content); + }); - relationshipSources.stream().filter((content) -> (content instanceof BlackboardArtifact)).forEachOrdered((content) -> { - artifactList.add((BlackboardArtifact) content); - }); - - } catch (TskCoreException ex) { - logger.log(Level.WARNING, "Unable to update selection.", ex); + } catch (TskCoreException ex) { + logger.log(Level.WARNING, "Unable to update selection.", ex); + } } - thumbnailViewer.resetComponent(); thumbnailViewer.setNode(new TableFilterNode(new DataResultFilterNode(new AbstractNode(new AttachmentThumbnailsChildren(artifactList)), tableEM), true, this.getClass().getName())); diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipBrowser.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipBrowser.java index 229a0067de..8910472295 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipBrowser.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 Basis Technology Corp. + * Copyright 2019-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +18,6 @@ */ package org.sleuthkit.autopsy.communications.relationships; -import java.awt.Component; import javax.swing.JPanel; import org.openide.util.Lookup; import org.sleuthkit.autopsy.communications.ModifiableProxyLookup; @@ -37,15 +36,15 @@ public final class RelationshipBrowser extends JPanel implements Lookup.Provider */ public RelationshipBrowser() { initComponents(); - + MessageViewer messagesViewer = new MessageViewer(); ContactsViewer contactsViewer = new ContactsViewer(); SummaryViewer summaryViewer = new SummaryViewer(); MediaViewer mediaViewer = new MediaViewer(); CallLogViewer callLogViewer = new CallLogViewer(); - + proxyLookup = new ModifiableProxyLookup(messagesViewer.getLookup()); - + tabPane.add(summaryViewer.getDisplayName(), summaryViewer); tabPane.add(messagesViewer.getDisplayName(), messagesViewer); tabPane.add(callLogViewer.getDisplayName(), callLogViewer); @@ -95,13 +94,11 @@ public final class RelationshipBrowser extends JPanel implements Lookup.Provider }// //GEN-END:initComponents private void tabPaneStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_tabPaneStateChanged - if(currentSelection != null) { - ((RelationshipsViewer) tabPane.getSelectedComponent()).setSelectionInfo(currentSelection); - } - - Component selectedComponent = tabPane.getSelectedComponent(); - if(selectedComponent instanceof Lookup.Provider) { - Lookup lookup = ((Lookup.Provider)selectedComponent).getLookup(); + RelationshipsViewer viewer = ((RelationshipsViewer) tabPane.getSelectedComponent()); + //clear old values + viewer.setSelectionInfo(currentSelection); + if (viewer instanceof Lookup.Provider) { + Lookup lookup = viewer.getLookup(); proxyLookup.setNewLookups(lookup); } }//GEN-LAST:event_tabPaneStateChanged diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java index 5d109438c3..aad1fe79a8 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2018-2020 Basis Technology Corp. + * Copyright 2018-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,10 +21,7 @@ package org.sleuthkit.autopsy.contentviewers; import java.awt.Component; import java.util.concurrent.ExecutionException; import java.util.logging.Level; -import javax.swing.JLabel; import javax.swing.SwingWorker; -import javax.swing.text.EditorKit; -import javax.swing.text.html.HTMLEditorKit; import static org.openide.util.NbBundle.Messages; import org.openide.nodes.Node; @@ -36,6 +33,7 @@ import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.autopsy.contentviewers.application.Annotations; import org.sleuthkit.autopsy.coreutils.Logger; import org.jsoup.nodes.Document; +import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerHtmlStyles; /** * Annotations view of file contents. @@ -48,33 +46,6 @@ import org.jsoup.nodes.Document; "AnnotationsContentViewer.onEmpty=No annotations were found for this particular item." }) public class AnnotationsContentViewer extends javax.swing.JPanel implements DataContentViewer { - - private static final int DEFAULT_FONT_SIZE = new JLabel().getFont().getSize(); - - // how big the subheader should be - private static final int SUBHEADER_FONT_SIZE = DEFAULT_FONT_SIZE * 12 / 11; - - // how big the header should be - private static final int HEADER_FONT_SIZE = DEFAULT_FONT_SIZE * 14 / 11; - - // the subsection indent - private static final int DEFAULT_SUBSECTION_LEFT_PAD = DEFAULT_FONT_SIZE; - - // spacing occurring after an item - private static final int DEFAULT_SECTION_SPACING = DEFAULT_FONT_SIZE * 2; - private static final int DEFAULT_SUBSECTION_SPACING = DEFAULT_FONT_SIZE / 2; - private static final int CELL_SPACING = DEFAULT_FONT_SIZE / 2; - - // additional styling for components - private static final String STYLE_SHEET_RULE - = String.format(" .%s { font-size: %dpx;font-style:italic; margin: 0px; padding: 0px; } ", Annotations.MESSAGE_CLASSNAME, DEFAULT_FONT_SIZE) - + String.format(" .%s {font-size:%dpx;font-weight:bold; margin: 0px; margin-top: %dpx; padding: 0px; } ", - Annotations.SUBHEADER_CLASSNAME, SUBHEADER_FONT_SIZE, DEFAULT_SUBSECTION_SPACING) - + String.format(" .%s { font-size:%dpx;font-weight:bold; margin: 0px; padding: 0px; } ", Annotations.HEADER_CLASSNAME, HEADER_FONT_SIZE) - + String.format(" td { vertical-align: top; font-size:%dpx; text-align: left; margin: 0px; padding: 0px %dpx 0px 0px;} ", DEFAULT_FONT_SIZE, CELL_SPACING) - + String.format(" th { vertical-align: top; text-align: left; margin: 0px; padding: 0px %dpx 0px 0px} ", DEFAULT_FONT_SIZE, CELL_SPACING) - + String.format(" .%s { margin: %dpx 0px; padding-left: %dpx; } ", Annotations.SUBSECTION_CLASSNAME, DEFAULT_SUBSECTION_SPACING, DEFAULT_SUBSECTION_LEFT_PAD) - + String.format(" .%s { margin-bottom: %dpx; } ", Annotations.SECTION_CLASSNAME, DEFAULT_SECTION_SPACING); private static final long serialVersionUID = 1L; private static final Logger logger = Logger.getLogger(AnnotationsContentViewer.class.getName()); @@ -86,13 +57,7 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data */ public AnnotationsContentViewer() { initComponents(); - Utilities.configureTextPaneAsHtml(textPanel); - // get html editor kit and apply additional style rules - EditorKit editorKit = textPanel.getEditorKit(); - if (editorKit instanceof HTMLEditorKit) { - HTMLEditorKit htmlKit = (HTMLEditorKit) editorKit; - htmlKit.getStyleSheet().addRule(STYLE_SHEET_RULE); - } + ContentViewerHtmlStyles.setupHtmlJTextPane(textPanel); } @Override @@ -223,7 +188,7 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data if(doc != null) { return doc.html(); } else { - return Bundle.AnnotationsContentViewer_onEmpty(); + return "" + Bundle.AnnotationsContentViewer_onEmpty() + ""; } } @@ -235,6 +200,7 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data try { String text = get(); + ContentViewerHtmlStyles.setStyles(textPanel); textPanel.setText(text); textPanel.setCaretPosition(0); } catch (InterruptedException | ExecutionException ex) { diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.form b/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.form index b175b6b512..8e6f123911 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.form +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.form @@ -41,8 +41,6 @@ - - diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.java b/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.java index f37cccb028..bd3671e44b 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.java @@ -20,16 +20,22 @@ package org.sleuthkit.autopsy.contentviewers; import java.awt.Component; import java.awt.Cursor; +import java.text.MessageFormat; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.logging.Level; +import java.util.stream.Stream; import javax.swing.SwingWorker; import org.apache.commons.lang3.StringUtils; import org.openide.nodes.Node; import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; import org.openide.util.lookup.ServiceProvider; +import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerHtmlStyles; import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer; +import org.sleuthkit.autopsy.coreutils.EscapeUtil; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.TimeZoneUtils; import org.sleuthkit.datamodel.AbstractFile; @@ -63,6 +69,7 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer { public Metadata() { initComponents(); customizeComponents(); + ContentViewerHtmlStyles.setupHtmlJTextPane(jTextPane1); } /** @@ -80,8 +87,6 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer { setPreferredSize(new java.awt.Dimension(100, 52)); - jScrollPane2.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); - jScrollPane2.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); jScrollPane2.setPreferredSize(new java.awt.Dimension(610, 52)); jTextPane1.setEditable(false); @@ -116,30 +121,59 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer { * selectAllMenuItem.addActionListener(actList); */ - Utilities.configureTextPaneAsHtml(jTextPane1); } private void setText(String str) { - jTextPane1.setText("" + str + ""); //NON-NLS + ContentViewerHtmlStyles.setupHtmlJTextPane(jTextPane1); + jTextPane1.setText("" + str + ""); //NON-NLS + } + + private void addHeader(StringBuilder sb, String header, boolean spaced) { + sb.append(MessageFormat.format("

{2}

", + (spaced) ? ContentViewerHtmlStyles.getSpacedSectionClassName() : "", + ContentViewerHtmlStyles.getHeaderClassName(), + header)); } private void startTable(StringBuilder sb) { - sb.append(""); //NON-NLS + sb.append(MessageFormat.format("
", + ContentViewerHtmlStyles.getIndentedClassName())); //NON-NLS } private void endTable(StringBuilder sb) { - sb.append("
"); //NON-NLS + sb.append(""); //NON-NLS } private void addRow(StringBuilder sb, String key, String value) { - sb.append(""); //NON-NLS - sb.append(key); - sb.append(""); //NON-NLS - sb.append(value); - sb.append(""); //NON-NLS + sb.append(MessageFormat.format("{2}:{4}", + ContentViewerHtmlStyles.getKeyColumnClassName(), + ContentViewerHtmlStyles.getTextClassName(), + EscapeUtil.escapeHtml(key), + ContentViewerHtmlStyles.getTextClassName(), + EscapeUtil.escapeHtml(key) + )); + } + + private void addMonospacedRow(StringBuilder sb, String key) { + sb.append(MessageFormat.format("{2}", + ContentViewerHtmlStyles.getKeyColumnClassName(), + ContentViewerHtmlStyles.getMonospacedClassName(), + EscapeUtil.escapeHtml(key) + )); + } + + private void addRowWithMultipleValues(StringBuilder sb, String key, String[] values) { + String[] safeValues = values == null || values.length < 1 ? new String[]{""} : values; + + addRow(sb, key, safeValues[0]); + Stream.of(safeValues) + .skip(1) + .filter(line -> line != null) + .forEach(line -> addRow(sb, "", EscapeUtil.escapeHtml(line))); } @Messages({ + "Metadata.headerTitle=Metadata", "Metadata.tableRowTitle.mimeType=MIME Type", "Metadata.nodeText.truncated=(results truncated)", "Metadata.tableRowTitle.sha1=SHA1", @@ -219,8 +253,11 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer { if (StringUtils.isEmpty(details)) { details = Bundle.Metadata_nodeText_unknown(); } - details = details.replaceAll("\n", "
"); - addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.acquisitionDetails"), details); + String[] lines = (details != null) ? details.split("\n") : new String[]{""}; + addRowWithMultipleValues(sb, + NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.acquisitionDetails"), + lines); + } catch (TskCoreException ex) { LOGGER.log(Level.SEVERE, "Error reading acquisition details from case database", ex); //NON-NLS } @@ -240,11 +277,9 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer { if (node != null && !node.getLookup().lookupAll(DataArtifact.class).isEmpty()) { return Bundle.Metadata_dataArtifactTitle(); } else { - return NbBundle.getMessage(this.getClass(), "Metadata.title"); + return NbBundle.getMessage(this.getClass(), "Metadata.title"); } } - - @Override public String getToolTip() { @@ -299,6 +334,7 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer { } StringBuilder sb = new StringBuilder(); + addHeader(sb, Bundle.Metadata_headerTitle(), false); startTable(sb); if (file != null) { @@ -357,30 +393,35 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer { * If we have a file system file, grab the more detailed * metadata text too */ - try { - if (file instanceof FsContent) { - FsContent fsFile = (FsContent) file; + if (file instanceof FsContent) { + FsContent fsFile = (FsContent) file; - sb.append("
\n"); //NON-NLS
-                        sb.append(NbBundle.getMessage(this.getClass(), "Metadata.nodeText.text"));
-                        sb.append(" 

"); // NON-NLS - for (String str : fsFile.getMetaDataText()) { - sb.append(str).append("
"); //NON-NLS + addHeader(sb, NbBundle.getMessage(this.getClass(), "Metadata.nodeText.text"), true); + startTable(sb); - /* + List istatStrings = Collections.emptyList(); + try { + istatStrings = fsFile.getMetaDataText(); + } catch (TskCoreException ex) { + istatStrings = Arrays.asList(NbBundle.getMessage(this.getClass(), "Metadata.nodeText.exceptionNotice.text") + ex.getLocalizedMessage()); + } + + for (String str : istatStrings) { + addMonospacedRow(sb, str); + + /* * Very long results can cause the UI to hang before * displaying, so truncate the results if necessary. - */ - if (sb.length() > 50000) { - sb.append(NbBundle.getMessage(this.getClass(), "Metadata.nodeText.truncated")); - break; - } + */ + if (sb.length() > 50000) { + addMonospacedRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.nodeText.truncated")); + break; } - sb.append("
\n"); //NON-NLS } - } catch (TskCoreException ex) { - sb.append(NbBundle.getMessage(this.getClass(), "Metadata.nodeText.exceptionNotice.text")).append(ex.getLocalizedMessage()); + + endTable(sb); } + } else { try { addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.name"), image.getUniquePath()); @@ -419,20 +460,18 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer { // Add all the data source paths to the "Local Path" value cell. String[] imagePaths = image.getPaths(); + + if (imagePaths.length > 0) { - StringBuilder pathValues = new StringBuilder("
"); - pathValues.append(imagePaths[0]); - pathValues.append("
"); - for (int i = 1; i < imagePaths.length; i++) { - pathValues.append("
"); - pathValues.append(imagePaths[i]); - pathValues.append("
"); - } - addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.localPath"), pathValues.toString()); + addRowWithMultipleValues(sb, + NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.localPath"), + imagePaths); } else { addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.localPath"), NbBundle.getMessage(this.getClass(), "Metadata.nodeText.none")); } + + endTable(sb); } if (isCancelled()) { diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsContentPanel.form b/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsContentPanel.form index 22fbe9e8a1..98fb50c89a 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsContentPanel.form +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsContentPanel.form @@ -42,9 +42,6 @@ - - - diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsContentPanel.java b/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsContentPanel.java index bf3c45d0f3..f365e8392e 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsContentPanel.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsContentPanel.java @@ -18,20 +18,21 @@ */ package org.sleuthkit.autopsy.contentviewers.analysisresults; -import java.awt.Color; import java.text.MessageFormat; import java.util.List; import java.util.Optional; -import javax.swing.JLabel; -import javax.swing.text.html.HTMLEditorKit; import org.apache.commons.lang3.tuple.Pair; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.openide.util.NbBundle; +import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.contentviewers.analysisresults.AnalysisResultsViewModel.NodeResults; import org.sleuthkit.autopsy.contentviewers.analysisresults.AnalysisResultsViewModel.ResultDisplayAttributes; +import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerHtmlStyles; +import org.sleuthkit.autopsy.coreutils.EscapeUtil; import org.sleuthkit.datamodel.AnalysisResult; +import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Score; /** @@ -40,57 +41,19 @@ import org.sleuthkit.datamodel.Score; public class AnalysisResultsContentPanel extends javax.swing.JPanel { private static final long serialVersionUID = 1L; - + private static final String EMPTY_HTML = ""; - private static final String DEFAULT_FONT_FAMILY = new JLabel().getFont().getFamily(); - private static final int DEFAULT_FONT_SIZE = new JLabel().getFont().getSize(); - private static final Color DEFAULT_BACKGROUND = new JLabel().getBackground(); - - // html stylesheet classnames for components - private static final String ANALYSIS_RESULTS_CLASS_PREFIX = "analysisResult_"; - private static final String SPACED_SECTION_CLASSNAME = ANALYSIS_RESULTS_CLASS_PREFIX + "spacedSection"; - private static final String SUBSECTION_CLASSNAME = ANALYSIS_RESULTS_CLASS_PREFIX + "subsection"; - private static final String HEADER_CLASSNAME = ANALYSIS_RESULTS_CLASS_PREFIX + "header"; - public static final String MESSAGE_CLASSNAME = ANALYSIS_RESULTS_CLASS_PREFIX + "message"; - public static final String TD_CLASSNAME = ANALYSIS_RESULTS_CLASS_PREFIX + "td"; - // Anchors are inserted into the navigation so that the viewer can navigate to a selection. // This is the prefix of those anchors. private static final String RESULT_ANCHOR_PREFIX = "AnalysisResult_"; - // how big the header should be - private static final int HEADER_FONT_SIZE = DEFAULT_FONT_SIZE + 2; - - // spacing occurring after an item - private static final int DEFAULT_SECTION_SPACING = DEFAULT_FONT_SIZE / 2; - private static final int CELL_SPACING = DEFAULT_FONT_SIZE / 2; - - // the subsection indent - private static final int DEFAULT_SUBSECTION_LEFT_PAD = DEFAULT_FONT_SIZE; - - // additional styling for components - private static final String STYLE_SHEET_RULE - = String.format(" .%s { font-size: %dpt;font-style:italic; margin: 0px; padding: 0px; } ", MESSAGE_CLASSNAME, DEFAULT_FONT_SIZE) - + String.format(" .%s { font-family: %s; font-size: %dpt; font-weight: bold; margin: 0px; padding: 0px; } ", - HEADER_CLASSNAME, DEFAULT_FONT_FAMILY, HEADER_FONT_SIZE) - + String.format(" .%s { vertical-align: top; font-family: %s; font-size: %dpt; text-align: left; margin: 0pt; padding: 0px %dpt 0px 0px;} ", - TD_CLASSNAME, DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE, CELL_SPACING) - + String.format(" .%s { margin-top: %dpt; } ", SPACED_SECTION_CLASSNAME, DEFAULT_SECTION_SPACING) - + String.format(" .%s { padding-left: %dpt; }", SUBSECTION_CLASSNAME, DEFAULT_SUBSECTION_LEFT_PAD); - - - /** * Creates new form AnalysisResultsContentViewer */ public AnalysisResultsContentPanel() { initComponents(); - - textPanel.setContentType("text/html;charset=UTF-8"); //NON-NLS - HTMLEditorKit kit = new HTMLEditorKit(); - textPanel.setEditorKit(kit); - kit.getStyleSheet().addRule(STYLE_SHEET_RULE); + ContentViewerHtmlStyles.setupHtmlJTextPane(textPanel); } /** @@ -99,10 +62,11 @@ public class AnalysisResultsContentPanel extends javax.swing.JPanel { * @param message The message to be displayed. */ void showMessage(String message) { + ContentViewerHtmlStyles.setStyles(textPanel); textPanel.setText("" - + MessageFormat.format("

{1}

", - MESSAGE_CLASSNAME, - message == null ? "" : message) + + MessageFormat.format("

{1}

", + ContentViewerHtmlStyles.getMessageClassName(), + message == null ? "" : EscapeUtil.escapeHtml(message)) + ""); } @@ -118,31 +82,26 @@ public class AnalysisResultsContentPanel extends javax.swing.JPanel { * * @param nodeResults The analysis results data to display. */ - @NbBundle.Messages("AnalysisResultsContentPanel_aggregateScore_displayKey=Aggregate Score") void displayResults(NodeResults nodeResults) { Document document = Jsoup.parse(EMPTY_HTML); Element body = document.getElementsByTag("body").first(); - // if there is an aggregate score, append a section with the value - Optional aggregateScore = nodeResults.getAggregateScore(); - if (aggregateScore.isPresent()) { - appendSection(body, - MessageFormat.format("{0}: {1}", - Bundle.AnalysisResultsContentPanel_aggregateScore_displayKey(), - aggregateScore.get().getSignificance().getDisplayName()), - Optional.empty()); - } + Optional panelHeader = appendPanelHeader(body, nodeResults.getContent(), nodeResults.getAggregateScore()); // for each analysis result item, display the data. List displayAttributes = nodeResults.getAnalysisResults(); for (int idx = 0; idx < displayAttributes.size(); idx++) { AnalysisResultsViewModel.ResultDisplayAttributes resultAttrs = displayAttributes.get(idx); - appendResult(body, idx, resultAttrs); + Element sectionDiv = appendResult(body, idx, resultAttrs); + if (idx > 0 || panelHeader.isPresent()) { + sectionDiv.attr("class", ContentViewerHtmlStyles.getSpacedSectionClassName()); + } } // set the body html + ContentViewerHtmlStyles.setStyles(textPanel); textPanel.setText(document.html()); - + // if there is a selected result scroll to it Optional selectedResult = nodeResults.getSelectedResult(); if (selectedResult.isPresent()) { @@ -153,34 +112,80 @@ public class AnalysisResultsContentPanel extends javax.swing.JPanel { } } + /** + * Appends the header to the panel. + * + * @param parent The parent html element. + * @param content The content whose name will be added if present. + * @param score The aggregate score whose significance will be added if + * present. + * + * @return The html element. + */ + @Messages({ + "AnalysisResultsContentPanel_aggregateScore_displayKey=Aggregate Score", + "AnalysisResultsContentPanel_content_displayKey=Item" + }) + private Optional appendPanelHeader(Element parent, Optional content, Optional score) { + if (!content.isPresent() || !score.isPresent()) { + return Optional.empty(); + } + + Element container = parent.appendElement("div"); + + // if there is content append the name + content.ifPresent((c) -> { + container.appendElement("p") + .attr("class", ContentViewerHtmlStyles.getTextClassName()) + .text(MessageFormat.format("{0}: {1}", + Bundle.AnalysisResultsContentPanel_content_displayKey(), + c.getName())); + }); + + // if there is an aggregate score, append the value + score.ifPresent((s) -> { + container.appendElement("p") + .attr("class", ContentViewerHtmlStyles.getTextClassName()) + .text(MessageFormat.format("{0}: {1}", + Bundle.AnalysisResultsContentPanel_aggregateScore_displayKey(), + s.getSignificance().getDisplayName())); + }); + + return Optional.ofNullable(container); + } + /** * Returns the anchor id to use with the analysis result (based on the id). + * * @param analysisResult The analysis result. + * * @return The anchor id. */ private String getAnchor(AnalysisResult analysisResult) { return RESULT_ANCHOR_PREFIX + analysisResult.getId(); } - /** * Appends a result item to the parent element of an html document. + * * @param parent The parent element. - * @param index The index of the item in the list of all items. - * @param attrs The attributes of this item. + * @param index The index of the item in the list of all items. + * @param attrs The attributes of this item. + * + * @return The result div. */ @NbBundle.Messages({"# {0} - analysisResultsNumber", "AnalysisResultsContentPanel_result_headerKey=Analysis Result {0}" }) - private void appendResult(Element parent, int index, AnalysisResultsViewModel.ResultDisplayAttributes attrs) { + private Element appendResult(Element parent, int index, AnalysisResultsViewModel.ResultDisplayAttributes attrs) { // create a new section with appropriate header Element sectionDiv = appendSection(parent, Bundle.AnalysisResultsContentPanel_result_headerKey(index + 1), Optional.ofNullable(getAnchor(attrs.getAnalysisResult()))); - + // create a table Element table = sectionDiv.appendElement("table"); - table.attr("class", SUBSECTION_CLASSNAME); + table.attr("class", ContentViewerHtmlStyles.getIndentedClassName()); Element tableBody = table.appendElement("tbody"); @@ -188,15 +193,20 @@ public class AnalysisResultsContentPanel extends javax.swing.JPanel { for (Pair keyVal : attrs.getAttributesToDisplay()) { Element row = tableBody.appendElement("tr"); String keyString = keyVal.getKey() == null ? "" : keyVal.getKey() + ":"; - row.appendElement("td") + Element keyTd = row.appendElement("td") + .attr("class", ContentViewerHtmlStyles.getTextClassName()); + + keyTd.appendElement("span") .text(keyString) - .attr("class", TD_CLASSNAME); + .attr("class", ContentViewerHtmlStyles.getKeyColumnClassName()); String valueString = keyVal.getValue() == null ? "" : keyVal.getValue(); row.appendElement("td") .text(valueString) - .attr("class", TD_CLASSNAME); + .attr("class", ContentViewerHtmlStyles.getTextClassName()); } + + return sectionDiv; } /** @@ -210,21 +220,25 @@ public class AnalysisResultsContentPanel extends javax.swing.JPanel { */ private Element appendSection(Element parent, String headerText, Optional anchorId) { Element sectionDiv = parent.appendElement("div"); - + // append an anchor tag if there is one + Element anchorEl = null; if (anchorId.isPresent()) { - Element anchorEl = sectionDiv.appendElement("a"); + anchorEl = sectionDiv.appendElement("a"); anchorEl.attr("name", anchorId.get()); + anchorEl.attr("style", "padding: 0px; margin: 0px; display: inline-block;"); } - // set the class for the section - sectionDiv.attr("class", SPACED_SECTION_CLASSNAME); - // append the header - Element header = sectionDiv.appendElement("h1"); + Element header = null; + header = (anchorEl == null) + ? sectionDiv.appendElement("h1") + : anchorEl.appendElement("h1"); + header.text(headerText); - header.attr("class", HEADER_CLASSNAME); - + header.attr("class", ContentViewerHtmlStyles.getHeaderClassName()); + header.attr("style", "display: inline-block"); + // return the section element return sectionDiv; } @@ -244,7 +258,6 @@ public class AnalysisResultsContentPanel extends javax.swing.JPanel { setPreferredSize(new java.awt.Dimension(100, 58)); textPanel.setEditable(false); - textPanel.setBackground(DEFAULT_BACKGROUND); textPanel.setName(""); // NOI18N textPanel.setPreferredSize(new java.awt.Dimension(600, 52)); scrollPane.setViewportView(textPanel); diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsViewModel.java b/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsViewModel.java index 8ba7308eb4..00cc170b14 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsViewModel.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsViewModel.java @@ -94,6 +94,7 @@ public class AnalysisResultsViewModel { private final List analysisResults; private final Optional selectedResult; private final Optional aggregateScore; + private final Optional content; /** * Constructor. @@ -102,11 +103,13 @@ public class AnalysisResultsViewModel { * @param selectedResult The selected analysis result or empty if none * selected. * @param aggregateScore The aggregate score or empty if no score. + * @param content The content associated with these results. */ - NodeResults(List analysisResults, Optional selectedResult, Optional aggregateScore) { + NodeResults(List analysisResults, Optional selectedResult, Optional aggregateScore, Optional content) { this.analysisResults = analysisResults; this.selectedResult = selectedResult; this.aggregateScore = aggregateScore; + this.content = content; } /** @@ -135,6 +138,17 @@ public class AnalysisResultsViewModel { Optional getAggregateScore() { return aggregateScore; } + + /** + * Returns the content associated with these results or empty if not + * present. + * + * @return The content associated with these results or empty if not + * present. + */ + Optional getContent() { + return content; + } } /** @@ -221,10 +235,11 @@ public class AnalysisResultsViewModel { */ NodeResults getAnalysisResults(Node node) { if (node == null) { - return new NodeResults(Collections.emptyList(), Optional.empty(), Optional.empty()); + return new NodeResults(Collections.emptyList(), Optional.empty(), Optional.empty(), Optional.empty()); } Optional aggregateScore = Optional.empty(); + Optional nodeContent = Optional.empty(); // maps id of analysis result to analysis result to prevent duplication Map allAnalysisResults = new HashMap<>(); Optional selectedResult = Optional.empty(); @@ -236,6 +251,8 @@ public class AnalysisResultsViewModel { } try { + nodeContent = Optional.of(content); + // get the aggregate score of that content aggregateScore = Optional.ofNullable(content.getAggregateScore()); @@ -273,6 +290,6 @@ public class AnalysisResultsViewModel { // get view model representation List displayAttributes = getOrderedDisplayAttributes(allAnalysisResults.values()); - return new NodeResults(displayAttributes, selectedResult, aggregateScore); + return new NodeResults(displayAttributes, selectedResult, aggregateScore, nodeContent); } } diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/application/Annotations.java b/Core/src/org/sleuthkit/autopsy/contentviewers/application/Annotations.java index feec2703dc..9651ddc518 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/application/Annotations.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/application/Annotations.java @@ -24,7 +24,6 @@ import java.util.List; import java.util.function.Function; import java.util.logging.Level; import java.util.stream.Collectors; -import javax.swing.JLabel; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.jsoup.Jsoup; @@ -39,6 +38,7 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeNormalizationException; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeUtil; +import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerHtmlStyles; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; @@ -80,18 +80,6 @@ public class Annotations { private static final String EMPTY_HTML = ""; - private static final int DEFAULT_FONT_SIZE = new JLabel().getFont().getSize(); - // spacing occurring after an item - private static final int DEFAULT_TABLE_SPACING = DEFAULT_FONT_SIZE; - - // html stylesheet classnames for components - public static final String MESSAGE_CLASSNAME = "message"; - public static final String SUBSECTION_CLASSNAME = "subsection"; - public static final String SUBHEADER_CLASSNAME = "subheader"; - public static final String SECTION_CLASSNAME = "section"; - public static final String HEADER_CLASSNAME = "header"; - public static final String VERTICAL_TABLE_CLASSNAME = "vertical-table"; - // describing table values for a tag private static final List> TAG_ENTRIES = Arrays.asList( new ItemEntry<>(Bundle.Annotations_tagEntryDataLabel_tag(), @@ -200,11 +188,11 @@ public class Annotations { * @return If any content was actually rendered. */ private static boolean renderArtifact(Element parent, BlackboardArtifact bba, Content sourceContent) { - boolean contentRendered = appendEntries(parent, TAG_CONFIG, getTags(bba), false); + boolean contentRendered = appendEntries(parent, TAG_CONFIG, getTags(bba), false, true); if (CentralRepository.isEnabled()) { List centralRepoComments = getCentralRepositoryData(bba); - boolean crRendered = appendEntries(parent, CR_COMMENTS_CONFIG, centralRepoComments, false); + boolean crRendered = appendEntries(parent, CR_COMMENTS_CONFIG, centralRepoComments, false, !contentRendered); contentRendered = contentRendered || crRendered; } @@ -213,12 +201,18 @@ public class Annotations { || BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID() == bba.getArtifactTypeID()) && (hasTskComment(bba))) { - boolean filesetRendered = appendEntries(parent, ARTIFACT_COMMENT_CONFIG, Arrays.asList(bba), false); + boolean filesetRendered = appendEntries(parent, ARTIFACT_COMMENT_CONFIG, Arrays.asList(bba), false, !contentRendered); contentRendered = contentRendered || filesetRendered; } Element sourceFileSection = appendSection(parent, Bundle.Annotations_sourceFile_title()); - boolean sourceFileRendered = renderContent(sourceFileSection, sourceContent, true); + sourceFileSection.attr("class", ContentViewerHtmlStyles.getSpacedSectionClassName()); + + Element sourceFileContainer = sourceFileSection.appendElement("div"); + sourceFileContainer.attr("class", ContentViewerHtmlStyles.getIndentedClassName()); + + + boolean sourceFileRendered = renderContent(sourceFileContainer, sourceContent, true); if (!sourceFileRendered) { sourceFileSection.remove(); @@ -238,24 +232,27 @@ public class Annotations { * @return If any content was actually rendered. */ private static boolean renderContent(Element parent, Content sourceContent, boolean isSubheader) { - boolean contentRendered = appendEntries(parent, TAG_CONFIG, getTags(sourceContent), isSubheader); + boolean contentRendered = appendEntries(parent, TAG_CONFIG, getTags(sourceContent), isSubheader, true); if (sourceContent instanceof AbstractFile) { AbstractFile sourceFile = (AbstractFile) sourceContent; if (CentralRepository.isEnabled()) { List centralRepoComments = getCentralRepositoryData(sourceFile); - boolean crRendered = appendEntries(parent, CR_COMMENTS_CONFIG, centralRepoComments, isSubheader); + boolean crRendered = appendEntries(parent, CR_COMMENTS_CONFIG, centralRepoComments, isSubheader, + !contentRendered); contentRendered = contentRendered || crRendered; } boolean hashsetRendered = appendEntries(parent, HASHSET_CONFIG, getFileSetHits(sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT), - isSubheader); + isSubheader, + !contentRendered); boolean interestingFileRendered = appendEntries(parent, INTERESTING_FILE_CONFIG, getFileSetHits(sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT), - isSubheader); + isSubheader, + !contentRendered); contentRendered = contentRendered || hashsetRendered || interestingFileRendered; } @@ -456,24 +453,36 @@ public class Annotations { * will be formatted as a table in the format specified in the * SectionConfig. * - * @param parent The parent element for which the entries will be - * attached. - * @param config The display configuration for this entry type (i.e. - * table type, name, if data is not present). - * @param items The items to display. - * @param isSubsection Whether or not this should be displayed as a - * subsection. If not displayed as a top-level section. + * @param parent The parent element for which the entries will be + * attached. + * @param config The display configuration for this entry type (i.e. + * table type, name, if data is not present). + * @param items The items to display. + * @param isSubsection Whether or not this should be displayed as a + * subsection. If not displayed as a top-level + * section. + * @param isFirstSection Whether or not this is the first section appended. * * @return If there was actual content rendered for this set of entries. */ private static boolean appendEntries(Element parent, Annotations.SectionConfig config, List items, - boolean isSubsection) { + boolean isSubsection, boolean isFirstSection) { if (items == null || items.isEmpty()) { return false; } Element sectionDiv = (isSubsection) ? appendSubsection(parent, config.getTitle()) : appendSection(parent, config.getTitle()); - appendVerticalEntryTables(sectionDiv, items, config.getAttributes()); + if (!isFirstSection) { + sectionDiv.attr("class", ContentViewerHtmlStyles.getSpacedSectionClassName()); + } + + Element sectionContainer = sectionDiv.appendElement("div"); + + if (!isSubsection) { + sectionContainer.attr("class", ContentViewerHtmlStyles.getIndentedClassName()); + } + + appendVerticalEntryTables(sectionContainer, items, config.getAttributes()); return true; } @@ -499,12 +508,11 @@ public class Annotations { .collect(Collectors.toList()); Element childTable = appendTable(parent, 2, tableData, null); - childTable.attr("class", VERTICAL_TABLE_CLASSNAME); if (isFirst) { isFirst = false; } else { - childTable.attr("style", String.format("margin-top: %dpx;", DEFAULT_TABLE_SPACING)); + childTable.attr("class", ContentViewerHtmlStyles.getSpacedSectionClassName()); } } @@ -551,6 +559,7 @@ public class Annotations { Element row = rowParent.appendElement("tr"); for (int i = 0; i < columnNumber; i++) { Element cell = row.appendElement(cellType); + cell.attr("class", ContentViewerHtmlStyles.getTextClassName()); if (data != null && i < data.size()) { cell.text(StringUtils.isEmpty(data.get(i)) ? "" : data.get(i)); } @@ -568,10 +577,9 @@ public class Annotations { */ private static Element appendSection(Element parent, String headerText) { Element sectionDiv = parent.appendElement("div"); - sectionDiv.attr("class", SECTION_CLASSNAME); Element header = sectionDiv.appendElement("h1"); header.text(headerText); - header.attr("class", HEADER_CLASSNAME); + header.attr("class", ContentViewerHtmlStyles.getHeaderClassName()); return sectionDiv; } @@ -585,10 +593,9 @@ public class Annotations { */ private static Element appendSubsection(Element parent, String headerText) { Element subsectionDiv = parent.appendElement("div"); - subsectionDiv.attr("class", SUBSECTION_CLASSNAME); Element header = subsectionDiv.appendElement("h2"); header.text(headerText); - header.attr("class", SUBHEADER_CLASSNAME); + header.attr("class", ContentViewerHtmlStyles.getHeaderClassName()); return subsectionDiv; } @@ -605,7 +612,7 @@ public class Annotations { private static Element appendMessage(Element parent, String message) { Element messageEl = parent.appendElement("p"); messageEl.text(message); - messageEl.attr("class", MESSAGE_CLASSNAME); + messageEl.attr("class", ContentViewerHtmlStyles.getMessageClassName()); return messageEl; } diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/CallLogArtifactViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/CallLogArtifactViewer.java index 8d27c6c5be..0830e8e6ef 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/CallLogArtifactViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/CallLogArtifactViewer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2020 Basis Technology Corp. + * Copyright 2020-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.contentviewers.artifactviewers; import java.awt.Component; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; +import java.awt.Insets; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -30,11 +31,13 @@ import java.util.Map; import java.util.Set; import java.util.logging.Level; import javax.swing.JScrollPane; +import javax.swing.border.EmptyBorder; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.openide.util.NbBundle; import org.openide.util.lookup.ServiceProvider; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; +import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerDefaults; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.guiutils.ContactCache; import org.sleuthkit.datamodel.BlackboardArtifact; @@ -75,6 +78,7 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac */ public CallLogArtifactViewer() { initComponents(); + this.setBorder(new EmptyBorder(ContentViewerDefaults.getPanelInsets())); } /** @@ -93,29 +97,28 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac public void setArtifact(BlackboardArtifact artifact) { resetComponent(); - if (artifact == null) { - return; - } - CallLogViewData callLogViewData = null; try { callLogViewData = getCallLogViewData(artifact); } catch (TskCoreException ex) { logger.log(Level.SEVERE, String.format("Error getting attributes for Calllog artifact (artifact_id=%d, obj_id=%d)", artifact.getArtifactID(), artifact.getObjectID()), ex); } - + List personaSearchDataList = new ArrayList<>(); // update the view with the call log data if (callLogViewData != null) { - List personaSearchDataList = updateView(callLogViewData); - if (!personaSearchDataList.isEmpty()) { - currentAccountFetcher = new PersonaAccountFetcher(artifact, personaSearchDataList, this); - currentAccountFetcher.execute(); - } else { - currentAccountFetcher = null; - } + personaSearchDataList.addAll(updateView(callLogViewData)); + } + if (!personaSearchDataList.isEmpty()) { + currentAccountFetcher = new PersonaAccountFetcher(artifact, personaSearchDataList, this); + currentAccountFetcher.execute(); + } else { + currentAccountFetcher = null; + } + // repaint this.revalidate(); + this.repaint(); } /** @@ -309,13 +312,13 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac }) private List updateView(CallLogViewData callLogViewData) { - CommunicationArtifactViewerHelper.addHeader(this, m_gridBagLayout, this.m_constraints, Bundle.CallLogArtifactViewer_heading_parties()); + CommunicationArtifactViewerHelper.addHeader(this, m_gridBagLayout, this.m_constraints, 0, Bundle.CallLogArtifactViewer_heading_parties()); List dataList = new ArrayList<>(); // Display "From" if we have non-local device accounts if (callLogViewData.getFromAccount() != null) { CommunicationArtifactViewerHelper.addKey(this, m_gridBagLayout, this.m_constraints, Bundle.CallLogArtifactViewer_label_from()); - + // check if this is local account String accountDisplayString = getAccountDisplayString(callLogViewData.getFromAccount(), callLogViewData); CommunicationArtifactViewerHelper.addValue(this, m_gridBagLayout, this.m_constraints, accountDisplayString); @@ -366,8 +369,6 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac this.setLayout(m_gridBagLayout); this.revalidate(); - this.repaint(); - return dataList; } @@ -384,7 +385,7 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac }) private void updateMetadataView(CallLogViewData callLogViewData) { - CommunicationArtifactViewerHelper.addHeader(this, m_gridBagLayout, this.m_constraints, Bundle.CallLogArtifactViewer_heading_metadata()); + CommunicationArtifactViewerHelper.addHeader(this, m_gridBagLayout, this.m_constraints, ContentViewerDefaults.getSectionSpacing(), Bundle.CallLogArtifactViewer_heading_metadata()); CommunicationArtifactViewerHelper.addKey(this, m_gridBagLayout, this.m_constraints, Bundle.CallLogArtifactViewer_label_direction()); if (callLogViewData.getDirection() != null) { @@ -414,7 +415,7 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac "CallLogArtifactViewer_heading_Source=Source", "CallLogArtifactViewer_label_datasource=Data Source",}) private void updateSourceView(CallLogViewData callLogViewData) { - CommunicationArtifactViewerHelper.addHeader(this, m_gridBagLayout, this.m_constraints, Bundle.CallLogArtifactViewer_heading_Source()); + CommunicationArtifactViewerHelper.addHeader(this, m_gridBagLayout, this.m_constraints, ContentViewerDefaults.getSectionSpacing(), Bundle.CallLogArtifactViewer_heading_Source()); CommunicationArtifactViewerHelper.addKey(this, m_gridBagLayout, this.m_constraints, Bundle.CallLogArtifactViewer_label_datasource()); CommunicationArtifactViewerHelper.addValue(this, m_gridBagLayout, this.m_constraints, callLogViewData.getDataSourceName()); } @@ -432,7 +433,7 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac if (callLogViewData.getOtherAttributes().isEmpty()) { return; } - CommunicationArtifactViewerHelper.addHeader(this, m_gridBagLayout, this.m_constraints, Bundle.CallLogArtifactViewer_heading_others()); + CommunicationArtifactViewerHelper.addHeader(this, m_gridBagLayout, this.m_constraints, ContentViewerDefaults.getSectionSpacing(), Bundle.CallLogArtifactViewer_heading_others()); for (Map.Entry entry : callLogViewData.getOtherAttributes().entrySet()) { CommunicationArtifactViewerHelper.addKey(this, m_gridBagLayout, this.m_constraints, entry.getKey()); @@ -444,9 +445,8 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac "CalllogArtifactViewer_cr_disabled_message=Enable Central Repository to view, create and edit personas." }) private void showCRDisabledMessage() { - CommunicationArtifactViewerHelper.addBlankLine(this, m_gridBagLayout, m_constraints); - m_constraints.gridy++; - CommunicationArtifactViewerHelper.addMessageRow(this, m_gridBagLayout, m_constraints, Bundle.ContactArtifactViewer_cr_disabled_message()); + Insets messageInsets = new Insets(ContentViewerDefaults.getSectionSpacing(), 0, ContentViewerDefaults.getLineSpacing(), 0); + CommunicationArtifactViewerHelper.addMessageRow(this, m_gridBagLayout, messageInsets, m_constraints, Bundle.ContactArtifactViewer_cr_disabled_message()); m_constraints.gridy++; } @@ -505,7 +505,7 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac m_constraints.gridx = 0; m_constraints.weighty = 0.0; m_constraints.weightx = 0.0; // keep components fixed horizontally. - m_constraints.insets = new java.awt.Insets(0, CommunicationArtifactViewerHelper.LEFT_INSET, 0, 0); + m_constraints.insets = new java.awt.Insets(0, ContentViewerDefaults.getSectionIndent(), 0, 0); m_constraints.fill = GridBagConstraints.NONE; } diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/CommunicationArtifactViewerHelper.java b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/CommunicationArtifactViewerHelper.java index fe5e19aff5..6f7e4cff2f 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/CommunicationArtifactViewerHelper.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/CommunicationArtifactViewerHelper.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2020 Basis Technology Corp. + * Copyright 2020-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,7 +19,6 @@ package org.sleuthkit.autopsy.contentviewers.artifactviewers; import java.awt.Dimension; -import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; @@ -38,6 +37,7 @@ import javax.swing.JTextPane; import javax.swing.SwingUtilities; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; +import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerDefaults; /** * @@ -49,8 +49,6 @@ final class CommunicationArtifactViewerHelper { // Number of columns in the gridbag layout. private final static int MAX_COLS = 4; - final static int LEFT_INSET = 12; - /** * Empty private constructor */ @@ -64,34 +62,34 @@ final class CommunicationArtifactViewerHelper { * @param panel Panel to update. * @param gridbagLayout Layout to use. * @param constraints Constraints to use. + * @param spacing Spacing to add to top insets (in pixels). * @param headerString Heading string to display. * * @return JLabel Heading label added. */ - static JLabel addHeader(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, String headerString) { + static JLabel addHeader(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, int topSpacing, String headerString) { Insets savedInsets = constraints.insets; // create label for heading javax.swing.JLabel headingLabel = new javax.swing.JLabel(); - // add a blank line before the start of new section, unless it's - // the first section - if (constraints.gridy != 0) { - addBlankLine(panel, gridbagLayout, constraints); - } + constraints.gridy++; constraints.gridx = 0; // let the header span all of the row constraints.gridwidth = MAX_COLS; - constraints.insets = new Insets(0, 0, 0, 0); // No inset for header + constraints.anchor = GridBagConstraints.LINE_START; + constraints.fill = GridBagConstraints.NONE; + + constraints.insets = new Insets(topSpacing, 0, ContentViewerDefaults.getLineSpacing(), 0); // set text - headingLabel.setText(headerString); + headingLabel.setText(headerString.trim()); // make it large and bold - headingLabel.setFont(headingLabel.getFont().deriveFont(Font.BOLD, headingLabel.getFont().getSize() + 2)); + headingLabel.setFont(ContentViewerDefaults.getHeaderFont()); // add to panel gridbagLayout.setConstraints(headingLabel, constraints); @@ -159,7 +157,7 @@ final class CommunicationArtifactViewerHelper { int savedFill = constraints.fill; constraints.weightx = 1.0; // take up all the horizontal space - constraints.fill = GridBagConstraints.BOTH; + constraints.fill = GridBagConstraints.HORIZONTAL; javax.swing.Box.Filler horizontalFiller = new javax.swing.Box.Filler(new Dimension(0, 0), new Dimension(0, 0), new Dimension(32767, 0)); gridbagLayout.setConstraints(horizontalFiller, constraints); @@ -181,6 +179,7 @@ final class CommunicationArtifactViewerHelper { static void addPageEndGlue(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints) { constraints.gridx = 0; + constraints.gridy++; double savedWeighty = constraints.weighty; int savedFill = constraints.fill; @@ -197,24 +196,6 @@ final class CommunicationArtifactViewerHelper { constraints.fill = savedFill; } - /** - * Adds a blank line to the panel. - * - * @param panel Panel to update. - * @param gridbagLayout Layout to use. - * @param constraints Constraints to use. - */ - static void addBlankLine(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints) { - constraints.gridy++; - constraints.gridx = 0; - - javax.swing.JLabel filler = new javax.swing.JLabel(" "); - gridbagLayout.setConstraints(filler, constraints); - panel.add(filler); - - addLineEndGlue(panel, gridbagLayout, constraints); - } - /** * Adds a label/key to the panel at col 0. * @@ -247,9 +228,12 @@ final class CommunicationArtifactViewerHelper { constraints.gridy++; constraints.gridx = gridx < MAX_COLS - 1 ? gridx : MAX_COLS - 2; + constraints.anchor = GridBagConstraints.LINE_START; + constraints.insets = new Insets(0, ContentViewerDefaults.getSectionIndent(), ContentViewerDefaults.getLineSpacing(), 0); // set text - keyLabel.setText(keyString + ": "); + String preppedKeyString = keyString == null ? null : keyString.trim() + ":"; + keyLabel.setText(preppedKeyString); // add to panel gridbagLayout.setConstraints(keyLabel, constraints); @@ -288,6 +272,7 @@ final class CommunicationArtifactViewerHelper { JTextPane valueField = new JTextPane(); valueField.setEditable(false); valueField.setOpaque(false); + valueField.setMargin(new Insets(0,0,0,0)); constraints.gridx = gridx < MAX_COLS ? gridx : MAX_COLS - 1; @@ -295,7 +280,8 @@ final class CommunicationArtifactViewerHelper { // let the value span 2 cols cloneConstraints.gridwidth = 2; - cloneConstraints.fill = GridBagConstraints.BOTH; + constraints.anchor = GridBagConstraints.LINE_START; + cloneConstraints.insets = new Insets(0, ContentViewerDefaults.getColumnSpacing(), ContentViewerDefaults.getLineSpacing(), 0); // set text valueField.setText(valueString); @@ -325,13 +311,13 @@ final class CommunicationArtifactViewerHelper { * @param panel Panel to show. * @param gridbagLayout Layout to use. * @param constraints Constraints to use. - * + * @param insets The insets to be used for the grid bag layout constraints. If null, default insets are assumed. * @param messageString Message to display. * * @return Label for message added. */ - static JLabel addMessageRow(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, String messageString) { - return addMessageRow(panel, gridbagLayout, constraints, messageString, 0); + static JLabel addMessageRow(JPanel panel, GridBagLayout gridbagLayout, Insets insets, GridBagConstraints constraints, String messageString) { + return addMessageRow(panel, gridbagLayout, constraints, insets, messageString, 0); } /** @@ -340,26 +326,33 @@ final class CommunicationArtifactViewerHelper { * * @param panel Panel to show. * @param gridbagLayout Layout to use. + * @param insets The insets to be used for the grid bag layout constraints. * @param constraints Constraints to use. - * + * @param insets The insets to be used for the grid bag layout constraints. If null, default insets are assumed. * @param messageString Message to display. + * @param gridx The grid x location to use. * * @return Label for message added. */ - static JLabel addMessageRow(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, String messageString, int gridx) { + static JLabel addMessageRow(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, Insets insets, String messageString, int gridx) { // create label javax.swing.JLabel messageLabel = new javax.swing.JLabel(); constraints.gridy++; constraints.gridx = gridx < MAX_COLS - 1 ? gridx : MAX_COLS - 2; - + constraints.insets = insets == null + ? new Insets(0, 0, ContentViewerDefaults.getLineSpacing(), 0) : + insets; + constraints.anchor = GridBagConstraints.LINE_START; + int savedGridwidth = constraints.gridwidth; constraints.gridwidth = 3; // set text - messageLabel.setText(messageString); + messageLabel.setText(messageString == null ? null : messageString.trim()); + messageLabel.setFont(ContentViewerDefaults.getMessageFont()); // add to panel gridbagLayout.setConstraints(messageLabel, constraints); @@ -406,8 +399,9 @@ final class CommunicationArtifactViewerHelper { Insets savedInsets = constraints.insets; // extra Indent in - constraints.insets = new java.awt.Insets(0, 2 * LEFT_INSET, 0, 0); - + constraints.insets = new java.awt.Insets(0, ContentViewerDefaults.getColumnSpacing(), ContentViewerDefaults.getLineSpacing(), 0); + constraints.anchor = GridBagConstraints.LINE_START; + // create label javax.swing.JLabel personaLabel = new javax.swing.JLabel(); String personaLabelText = Bundle.CommunicationArtifactViewerHelper_persona_label(); @@ -415,15 +409,12 @@ final class CommunicationArtifactViewerHelper { ? Bundle.CommunicationArtifactViewerHelper_persona_searching() : Bundle.CommunicationArtifactViewerHelper_persona_unknown()); - personaLabel.setText(personaLabelText); - + personaLabel.setText(personaLabelText == null ? null : personaLabelText.trim()); + // add to panel gridbagLayout.setConstraints(personaLabel, constraints); panel.add(personaLabel); - // restore constraint - constraints.insets = savedInsets; - constraints.gridx++; // Place a button as place holder. It will be enabled when persona is available. @@ -441,6 +432,9 @@ final class CommunicationArtifactViewerHelper { } else { personaLabel.setEnabled(false); } + + // restore constraint + constraints.insets = savedInsets; addLineEndGlue(panel, gridbagLayout, constraints); @@ -469,7 +463,7 @@ final class CommunicationArtifactViewerHelper { GridBagConstraints indentedConstraints = (GridBagConstraints) constraints.clone(); // Add an indent to match persona labels - indentedConstraints.insets = new java.awt.Insets(0, 2 * LEFT_INSET, 0, 0); + indentedConstraints.insets = new java.awt.Insets(0, ContentViewerDefaults.getSectionIndent(), ContentViewerDefaults.getLineSpacing(), 0); String contactInfo = Bundle.CommunicationArtifactViewerHelper_contact_label(contactId != null && !contactId.isEmpty() ? contactId : Bundle.CommunicationArtifactViewerHelper_contact_label_unknown()); diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/ContactArtifactViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/ContactArtifactViewer.java index b17263a26d..2b583ff000 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/ContactArtifactViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/ContactArtifactViewer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2020 Basis Technology Corp. + * Copyright 2020-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -41,9 +41,9 @@ import javax.imageio.ImageIO; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JLabel; -import javax.swing.JOptionPane; import javax.swing.JScrollPane; import javax.swing.SwingWorker; +import javax.swing.border.EmptyBorder; import org.apache.commons.lang.StringUtils; import org.openide.util.NbBundle; import org.openide.util.lookup.ServiceProvider; @@ -57,6 +57,7 @@ import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsDialog; import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsDialogCallback; import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsMode; import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsPanel; +import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerDefaults; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Account; @@ -107,7 +108,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac */ public ContactArtifactViewer() { initComponents(); - + this.setBorder(new EmptyBorder(ContentViewerDefaults.getPanelInsets())); defaultImage = new ImageIcon(ContactArtifactViewer.class.getResource(DEFAULT_IMAGE_PATH)); } @@ -129,19 +130,15 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac // Reset the panel. resetComponent(); - if (artifact == null) { - return; + if (artifact != null) { + try { + extractArtifactData(artifact); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, String.format("Error getting attributes for artifact (artifact_id=%d, obj_id=%d)", artifact.getArtifactID(), artifact.getObjectID()), ex); + return; + } + updateView(); } - - try { - extractArtifactData(artifact); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, String.format("Error getting attributes for artifact (artifact_id=%d, obj_id=%d)", artifact.getArtifactID(), artifact.getObjectID()), ex); - return; - } - - updateView(); - this.setLayout(this.m_gridBagLayout); this.revalidate(); this.repaint(); @@ -163,6 +160,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac * Extracts data from the artifact to be displayed in the panel. * * @param artifact Artifact to show. + * * @throws TskCoreException */ private void extractArtifactData(BlackboardArtifact artifact) throws TskCoreException { @@ -234,7 +232,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac /** * Updates the contact image in the view. * - * @param contactPanelLayout Panel layout. + * @param contactPanelLayout Panel layout. * @param contactPanelConstraints Layout constraints. * */ @@ -245,8 +243,11 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac Insets savedInsets = contactPanelConstraints.insets; contactPanelConstraints.gridy = 0; contactPanelConstraints.gridx = 0; - contactPanelConstraints.insets = new Insets(0, 0, 0, 0); - + contactPanelConstraints.insets = new Insets(0, 0, ContentViewerDefaults.getLineSpacing(), 0); + int prevGridWidth = contactPanelConstraints.gridwidth; + contactPanelConstraints.gridwidth = 3; + contactPanelConstraints.anchor = GridBagConstraints.LINE_START; + javax.swing.JLabel contactImage = new javax.swing.JLabel(); contactImage.setIcon(getImageFromArtifact(contactArtifact)); contactImage.setText(Bundle.ContactArtifactViewer_contactImage_text()); @@ -256,13 +257,14 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac CommunicationArtifactViewerHelper.addLineEndGlue(this, contactPanelLayout, contactPanelConstraints); contactPanelConstraints.gridy++; + contactPanelConstraints.gridwidth = prevGridWidth; contactPanelConstraints.insets = savedInsets; } /** * Updates the contact name in the view. * - * @param contactPanelLayout Panel layout. + * @param contactPanelLayout Panel layout. * @param contactPanelConstraints Layout constraints. * */ @@ -275,13 +277,13 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac if (StringUtils.isEmpty(bba.getValueString()) == false) { contactName = bba.getDisplayString(); - CommunicationArtifactViewerHelper.addHeader(this, contactPanelLayout, contactPanelConstraints, contactName); + CommunicationArtifactViewerHelper.addHeader(this, contactPanelLayout, contactPanelConstraints, 0, contactName); foundName = true; break; } } if (foundName == false) { - CommunicationArtifactViewerHelper.addHeader(this, contactPanelLayout, contactPanelConstraints, Bundle.ContactArtifactViewer_contactname_unknown()); + CommunicationArtifactViewerHelper.addHeader(this, contactPanelLayout, contactPanelConstraints, ContentViewerDefaults.getSectionSpacing(), Bundle.ContactArtifactViewer_contactname_unknown()); } } @@ -289,9 +291,9 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac * Updates the view by displaying the given list of attributes in the given * section panel. * - * @param sectionAttributesList List of attributes to display. - * @param sectionHeader Section name label. - * @param contactPanelLayout Panel layout. + * @param sectionAttributesList List of attributes to display. + * @param sectionHeader Section name label. + * @param contactPanelLayout Panel layout. * @param contactPanelConstraints Layout constraints. * */ @@ -302,7 +304,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac return; } - CommunicationArtifactViewerHelper.addHeader(this, contactPanelLayout, contactPanelConstraints, sectionHeader); + CommunicationArtifactViewerHelper.addHeader(this, contactPanelLayout, contactPanelConstraints, ContentViewerDefaults.getSectionSpacing(), sectionHeader); for (BlackboardAttribute bba : sectionAttributesList) { CommunicationArtifactViewerHelper.addKey(this, contactPanelLayout, contactPanelConstraints, bba.getAttributeType().getDisplayName()); CommunicationArtifactViewerHelper.addValue(this, contactPanelLayout, contactPanelConstraints, bba.getDisplayString()); @@ -316,7 +318,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac "ContactArtifactViewer_heading_Source=Source", "ContactArtifactViewer_label_datasource=Data Source",}) private void updateSource() { - CommunicationArtifactViewerHelper.addHeader(this, this.m_gridBagLayout, m_constraints, Bundle.ContactArtifactViewer_heading_Source()); + CommunicationArtifactViewerHelper.addHeader(this, this.m_gridBagLayout, m_constraints, ContentViewerDefaults.getSectionSpacing(), Bundle.ContactArtifactViewer_heading_Source()); CommunicationArtifactViewerHelper.addKey(this, m_gridBagLayout, m_constraints, Bundle.ContactArtifactViewer_label_datasource()); CommunicationArtifactViewerHelper.addValue(this, m_gridBagLayout, m_constraints, datasourceName); } @@ -335,7 +337,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac private void initiatePersonasSearch() { // add a section header - JLabel personaHeader = CommunicationArtifactViewerHelper.addHeader(this, m_gridBagLayout, m_constraints, Bundle.ContactArtifactViewer_persona_header()); + JLabel personaHeader = CommunicationArtifactViewerHelper.addHeader(this, m_gridBagLayout, m_constraints, ContentViewerDefaults.getSectionSpacing(), Bundle.ContactArtifactViewer_persona_header()); m_constraints.gridy++; @@ -346,8 +348,10 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac this.personaSearchStatusLabel = new javax.swing.JLabel(); personaSearchStatusLabel.setText(personaStatusLabelText); - + personaSearchStatusLabel.setFont(ContentViewerDefaults.getMessageFont()); + m_constraints.gridx = 0; + m_constraints.anchor = GridBagConstraints.LINE_START; CommunicationArtifactViewerHelper.addComponent(this, m_gridBagLayout, m_constraints, personaSearchStatusLabel); @@ -359,9 +363,8 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac personaHeader.setEnabled(false); personaSearchStatusLabel.setEnabled(false); - CommunicationArtifactViewerHelper.addBlankLine(this, m_gridBagLayout, m_constraints); - m_constraints.gridy++; - CommunicationArtifactViewerHelper.addMessageRow(this, m_gridBagLayout, m_constraints, Bundle.ContactArtifactViewer_cr_disabled_message()); + Insets messageInsets = new Insets(ContentViewerDefaults.getSectionSpacing(), 0, ContentViewerDefaults.getLineSpacing(), 0); + CommunicationArtifactViewerHelper.addMessageRow(this, m_gridBagLayout, messageInsets, m_constraints, Bundle.ContactArtifactViewer_cr_disabled_message()); m_constraints.gridy++; CommunicationArtifactViewerHelper.addPageEndGlue(this, m_gridBagLayout, this.m_constraints); @@ -412,12 +415,12 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac /** * Displays the given persona in the persona panel. * - * @param persona Persona to display. - * @param matchNumber Number of matches. + * @param persona Persona to display. + * @param matchNumber Number of matches. * @param missingAccountsList List of contact accounts this persona may be - * missing. - * @param gridBagLayout Layout to use. - * @param constraints layout constraints. + * missing. + * @param gridBagLayout Layout to use. + * @param constraints layout constraints. * * @throws CentralRepoException */ @@ -435,12 +438,9 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac // save the original insets Insets savedInsets = constraints.insets; - // some label are indented 2x to appear indented w.r.t column above - Insets extraIndentInsets = new java.awt.Insets(0, 2 * CommunicationArtifactViewerHelper.LEFT_INSET, 0, 0); - // Add a Match X label in col 0. constraints.gridx = 0; - javax.swing.JLabel matchNumberLabel = CommunicationArtifactViewerHelper.addKey(this, gridBagLayout, constraints, String.format("%s %d", Bundle.ContactArtifactViewer_persona_match_num(), matchNumber)); + javax.swing.JLabel matchNumberLabel = CommunicationArtifactViewerHelper.addKey(this, gridBagLayout, constraints, String.format("%s %d", Bundle.ContactArtifactViewer_persona_match_num(), matchNumber).trim()); javax.swing.JLabel personaNameLabel = new javax.swing.JLabel(); javax.swing.JButton personaButton = new javax.swing.JButton(); @@ -461,6 +461,8 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac //constraints.gridwidth = 1; // TBD: this may not be needed if we use single panel constraints.gridx++; + constraints.insets = new Insets(0, ContentViewerDefaults.getColumnSpacing(), ContentViewerDefaults.getLineSpacing(), 0); + constraints.anchor = GridBagConstraints.LINE_START; personaNameLabel.setText(personaName); gridBagLayout.setConstraints(personaNameLabel, constraints); CommunicationArtifactViewerHelper.addComponent(this, gridBagLayout, constraints, personaNameLabel); @@ -474,6 +476,8 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac // Shirnk the button height. personaButton.setMargin(new Insets(0, 5, 0, 5)); + constraints.insets = new Insets(0, ContentViewerDefaults.getColumnSpacing(), ContentViewerDefaults.getLineSpacing(), 0); + constraints.anchor = GridBagConstraints.LINE_START; gridBagLayout.setConstraints(personaButton, constraints); CommunicationArtifactViewerHelper.addComponent(this, gridBagLayout, constraints, personaButton); CommunicationArtifactViewerHelper.addLineEndGlue(this, gridBagLayout, constraints); @@ -488,7 +492,8 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac //constraints.insets = labelInsets; javax.swing.JLabel accountsStatus = new javax.swing.JLabel(Bundle.ContactArtifactViewer_found_all_accounts_label()); - constraints.insets = extraIndentInsets; + constraints.insets = new Insets(0, ContentViewerDefaults.getColumnSpacing(), ContentViewerDefaults.getLineSpacing(), 0); + constraints.anchor = GridBagConstraints.LINE_START; CommunicationArtifactViewerHelper.addComponent(this, gridBagLayout, constraints, accountsStatus); constraints.insets = savedInsets; @@ -501,7 +506,6 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac constraints.gridy++; // this needs an extra indent - constraints.insets = extraIndentInsets; CommunicationArtifactViewerHelper.addKeyAtCol(this, gridBagLayout, constraints, Bundle.ContactArtifactViewer_missing_account_label(), 1); constraints.insets = savedInsets; @@ -544,12 +548,12 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac m_gridBagLayout = new GridBagLayout(); m_constraints = new GridBagConstraints(); - m_constraints.anchor = GridBagConstraints.FIRST_LINE_START; + m_constraints.anchor = GridBagConstraints.LINE_START; m_constraints.gridy = 0; m_constraints.gridx = 0; m_constraints.weighty = 0.0; m_constraints.weightx = 0.0; // keep components fixed horizontally. - m_constraints.insets = new java.awt.Insets(0, CommunicationArtifactViewerHelper.LEFT_INSET, 0, 0); + m_constraints.insets = new java.awt.Insets(0, ContentViewerDefaults.getSectionIndent(), 0, 0); m_constraints.fill = GridBagConstraints.NONE; } @@ -560,7 +564,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac * @param artifact * * @return Image from a TSK_CONTACT artifact or default image if none was - * found or the artifact is not a TSK_CONTACT + * found or the artifact is not a TSK_CONTACT */ private ImageIcon getImageFromArtifact(BlackboardArtifact artifact) { ImageIcon imageIcon = defaultImage; @@ -610,7 +614,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac * Creates a persona searcher task. * * @param accountAttributesList List of attributes that may map to - * accounts. + * accounts. */ ContactPersonaSearcherTask(BlackboardArtifact artifact) { this.artifact = artifact; @@ -640,7 +644,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac } } } - + Collection personaAccounts = PersonaAccount.getPersonaAccountsForAccount(account); if (personaAccounts != null && !personaAccounts.isEmpty()) { // get personas for the account @@ -709,7 +713,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac /** * Constructor. * - * @param personaNameLabel Persona name label. + * @param personaNameLabel Persona name label. * @param personaActionButton Persona action button. */ PersonaUIComponents(JLabel personaNameLabel, JButton personaActionButton) { @@ -777,8 +781,8 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac for (CentralRepoAccount account : contactUniqueAccountsList) { personaPanel.addAccount(account, Bundle.ContactArtifactViewer_persona_account_justification(), Persona.Confidence.HIGH); } - - if(contactName != null && contactUniqueAccountsList.isEmpty()) { + + if (contactName != null && contactUniqueAccountsList.isEmpty()) { createPersonaDialog.setStartupPopupMessage(Bundle.ContactArtifactViewer_id_not_found_in_cr(contactName)); } diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/GeneralPurposeArtifactViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/GeneralPurposeArtifactViewer.java index d8150a91a2..e81b6705c6 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/GeneralPurposeArtifactViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/GeneralPurposeArtifactViewer.java @@ -18,9 +18,9 @@ */ package org.sleuthkit.autopsy.contentviewers.artifactviewers; +import java.awt.Color; import java.awt.Component; import java.awt.Dimension; -import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; @@ -30,18 +30,24 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Level; +import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.swing.JLabel; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; import javax.swing.JTextPane; import javax.swing.SwingUtilities; +import javax.swing.border.EmptyBorder; import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.tuple.Pair; import org.openide.util.NbBundle; import org.openide.util.lookup.ServiceProvider; +import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerDefaults; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.coreutils.TimeZoneUtils; @@ -55,13 +61,18 @@ import org.sleuthkit.datamodel.TskCoreException; */ @ServiceProvider(service = ArtifactContentViewer.class) public class GeneralPurposeArtifactViewer extends AbstractArtifactDetailsPanel implements ArtifactContentViewer { - + private static final long serialVersionUID = 1L; private static final Logger logger = Logger.getLogger(GeneralPurposeArtifactViewer.class.getName()); // Number of columns in the gridbag layout. private final static int MAX_COLS = 4; - private final static Insets ROW_INSETS = new java.awt.Insets(0, 12, 0, 0); - private final static Insets HEADER_INSETS = new java.awt.Insets(0, 0, 0, 0); + private final static Insets ZERO_INSETS = new java.awt.Insets(0, 0, 0, 0); + + private final static Insets FIRST_HEADER_INSETS = ZERO_INSETS; + private final static Insets HEADER_INSETS = new Insets(ContentViewerDefaults.getSectionSpacing(), 0, ContentViewerDefaults.getLineSpacing(), 0); + private final static Insets VALUE_COLUMN_INSETS = new Insets(0, ContentViewerDefaults.getColumnSpacing(), ContentViewerDefaults.getLineSpacing(), 0); + private final static Insets KEY_COLUMN_INSETS = new Insets(0, ContentViewerDefaults.getSectionIndent(), ContentViewerDefaults.getLineSpacing(), 0); + private final static double GLUE_WEIGHT_X = 1.0; private final static double TEXT_WEIGHT_X = 0.0; private final static int LABEL_COLUMN = 0; @@ -91,6 +102,7 @@ public class GeneralPurposeArtifactViewer extends AbstractArtifactDetailsPanel i initComponents(); gridBagConstraints.anchor = GridBagConstraints.FIRST_LINE_START; detailsPanel.setLayout(gridBagLayout); + detailsPanel.setBorder(new EmptyBorder(ContentViewerDefaults.getPanelInsets())); } /** @@ -180,7 +192,7 @@ public class GeneralPurposeArtifactViewer extends AbstractArtifactDetailsPanel i gridBagConstraints.weighty = 0.0; gridBagConstraints.weightx = TEXT_WEIGHT_X; // keep components fixed horizontally. gridBagConstraints.fill = GridBagConstraints.NONE; - gridBagConstraints.insets = ROW_INSETS; + gridBagConstraints.insets = ZERO_INSETS; } @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @@ -386,29 +398,26 @@ public class GeneralPurposeArtifactViewer extends AbstractArtifactDetailsPanel i headingLabel.setEditable(false); // add a blank line before the start of new section, unless it's // the first section - if (gridBagConstraints.gridy != 0) { - gridBagConstraints.gridy++; - // add to panel - addToPanel(new javax.swing.JLabel(" ")); - addLineEndGlue(); - headingLabel.setFocusable(false); - } + gridBagConstraints.insets = (gridBagConstraints.gridy == 0) + ? FIRST_HEADER_INSETS + : HEADER_INSETS; + gridBagConstraints.gridy++; gridBagConstraints.gridx = LABEL_COLUMN;; // let the header span all of the row gridBagConstraints.gridwidth = MAX_COLS; - gridBagConstraints.insets = HEADER_INSETS; // set text headingLabel.setText(headerString); // make it large and bold - headingLabel.setFont(headingLabel.getFont().deriveFont(Font.BOLD, headingLabel.getFont().getSize() + 2)); + headingLabel.setFont(ContentViewerDefaults.getHeaderFont()); + headingLabel.setMargin(ZERO_INSETS); // add to panel addToPanel(headingLabel); // reset constraints to normal gridBagConstraints.gridwidth = LABEL_WIDTH; // add line end glue addLineEndGlue(); - gridBagConstraints.insets = ROW_INSETS; + gridBagConstraints.insets = ZERO_INSETS; return headingLabel; } @@ -465,6 +474,7 @@ public class GeneralPurposeArtifactViewer extends AbstractArtifactDetailsPanel i javax.swing.JLabel keyLabel = new javax.swing.JLabel(); keyLabel.setFocusable(false); gridBagConstraints.gridy++; + gridBagConstraints.insets = KEY_COLUMN_INSETS; gridBagConstraints.gridx = LABEL_COLUMN; gridBagConstraints.gridwidth = LABEL_WIDTH; // set text @@ -492,7 +502,9 @@ public class GeneralPurposeArtifactViewer extends AbstractArtifactDetailsPanel i valueField.setFocusable(false); valueField.setEditable(false); valueField.setOpaque(false); + valueField.setMargin(ZERO_INSETS); gridBagConstraints.gridx = VALUE_COLUMN; + gridBagConstraints.insets = VALUE_COLUMN_INSETS; GridBagConstraints cloneConstraints = (GridBagConstraints) gridBagConstraints.clone(); // let the value span 2 cols cloneConstraints.gridwidth = VALUE_WIDTH; diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/MessageAccountPanel.java b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/MessageAccountPanel.java index fbf1ada856..c2847223e6 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/MessageAccountPanel.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/MessageAccountPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2020 Basis Technology Corp. + * Copyright 2020-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.contentviewers.artifactviewers; import java.awt.Dimension; +import java.awt.Insets; import java.awt.Toolkit; import java.awt.datatransfer.StringSelection; import java.awt.event.ActionEvent; @@ -44,6 +45,7 @@ import javax.swing.JTextPane; import javax.swing.LayoutStyle.ComponentPlacement; import javax.swing.SwingUtilities; import javax.swing.SwingWorker; +import javax.swing.border.EmptyBorder; import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; @@ -56,6 +58,7 @@ import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsDialog; import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsDialogCallback; import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsMode; import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsPanel; +import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerDefaults; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.guiutils.ContactCache; import org.sleuthkit.datamodel.Account; @@ -77,6 +80,15 @@ final class MessageAccountPanel extends JPanel { private AccountFetcher currentFetcher = null; + + + /** + * Main constructor. + */ + MessageAccountPanel() { + this.setBorder(new EmptyBorder(ContentViewerDefaults.getPanelInsets())); + } + /** * Set the new artifact for the panel. * @@ -170,9 +182,7 @@ final class MessageAccountPanel extends JPanel { layout.setHorizontalGroup( layout.createParallelGroup(Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addGroup(getMainHorizontalGroup(layout, dataList)) - .addContainerGap(158, Short.MAX_VALUE))); + .addGroup(getMainHorizontalGroup(layout, dataList)))); layout.setVerticalGroup(getMainVerticalGroup(layout, dataList)); setLayout(layout); @@ -186,6 +196,7 @@ final class MessageAccountPanel extends JPanel { messageLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); messageLabel.setText(Bundle.MessageAccountPanel_no_matches()); + messageLabel.setFont(ContentViewerDefaults.getMessageFont()); messageLabel.setEnabled(false); messagePanel.add(messageLabel, java.awt.BorderLayout.CENTER); @@ -224,14 +235,12 @@ final class MessageAccountPanel extends JPanel { private ParallelGroup getMainVerticalGroup(GroupLayout layout, List data) { SequentialGroup group = layout.createSequentialGroup(); for (AccountContainer o : data) { - group.addGap(5) - .addComponent(o.getAccountLabel()) + group.addComponent(o.getAccountLabel()) .addGroup(o.getContactLineVerticalGroup(layout)) .addGroup(o.getPersonLineVerticalGroup(layout)); + group.addGap(ContentViewerDefaults.getSectionSpacing()); } - group.addContainerGap(83, Short.MAX_VALUE); - return layout.createParallelGroup().addGroup(group); } @@ -259,12 +268,11 @@ final class MessageAccountPanel extends JPanel { private SequentialGroup getPersonaHorizontalGroup(GroupLayout layout, List data) { SequentialGroup group = layout.createSequentialGroup(); ParallelGroup pgroup = layout.createParallelGroup(Alignment.LEADING); - group.addGap(10); for (AccountContainer o : data) { pgroup.addGroup(o.getPersonaSequentialGroup(layout)); pgroup.addGroup(o.getContactSequentialGroup(layout)); } - group.addGap(10) + group.addGap(ContentViewerDefaults.getSectionIndent()) .addGroup(pgroup) .addPreferredGap(ComponentPlacement.RELATED) .addGroup(getButtonGroup(layout, data)); @@ -343,7 +351,9 @@ final class MessageAccountPanel extends JPanel { button = new JButton(); button.addActionListener(new PersonaButtonListener(this)); + accountLabel.setMargin(new Insets(0, 0, 0, 0)); accountLabel.setText(account.getTypeSpecificID()); + accountLabel.setFont(ContentViewerDefaults.getHeaderFont()); contactDisplayName.setText(contactName); personaDisplayName.setText(persona != null ? persona.getName() : Bundle.MessageAccountPanel_unknown_label()); diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextSourcePanel.form b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextSourcePanel.form index c57a0990a8..9b2e224b22 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextSourcePanel.form +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextSourcePanel.form @@ -2,11 +2,17 @@
- - + + + + + + + + - + @@ -24,15 +30,13 @@ - - + - - + - + @@ -41,14 +45,13 @@ - - + diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextSourcePanel.java b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextSourcePanel.java index 02bd3f2ae6..0f7d2855bf 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextSourcePanel.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextSourcePanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2020 Basis Technology Corp. + * Copyright 2020-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.contentviewers.contextviewer; import java.util.ArrayList; import java.util.List; import org.sleuthkit.autopsy.contentviewers.contextviewer.ContextViewer.DateTimePanel; +import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerDefaults; import org.sleuthkit.autopsy.directorytree.DirectoryTreeTopComponent; import org.sleuthkit.datamodel.BlackboardArtifact; import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT; @@ -75,8 +76,10 @@ public final class ContextSourcePanel extends javax.swing.JPanel implements Date jSourceNameLabel = new javax.swing.JLabel(); jSourceTextLabel = new javax.swing.JLabel(); - setBackground(new java.awt.Color(255, 255, 255)); - setPreferredSize(new java.awt.Dimension(495, 75)); + setBackground(ContentViewerDefaults.getPanelBackground()); + setMaximumSize(new java.awt.Dimension(495, 55)); + setMinimumSize(new java.awt.Dimension(300, 55)); + setPreferredSize(new java.awt.Dimension(495, 55)); org.openide.awt.Mnemonics.setLocalizedText(jSourceGoToResultButton, org.openide.util.NbBundle.getMessage(ContextSourcePanel.class, "ContextSourcePanel.jSourceGoToResultButton.text")); // NOI18N jSourceGoToResultButton.addActionListener(new java.awt.event.ActionListener() { @@ -94,26 +97,23 @@ public final class ContextSourcePanel extends javax.swing.JPanel implements Date layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addGap(50, 50, 50) .addComponent(jSourceNameLabel) .addGap(36, 36, 36) - .addComponent(jSourceTextLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGap(260, 260, 260)) + .addComponent(jSourceTextLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 360, Short.MAX_VALUE)) .addGroup(layout.createSequentialGroup() - .addGap(90, 90, 90) + .addGap(40, 40, 40) .addComponent(jSourceGoToResultButton) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addGap(2, 2, 2) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jSourceNameLabel) .addComponent(jSourceTextLabel)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jSourceGoToResultButton) - .addGap(0, 0, 0)) + .addGap(0, 11, Short.MAX_VALUE)) ); }// //GEN-END:initComponents diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextUsagePanel.form b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextUsagePanel.form index a3e2a90f84..2faf5bf779 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextUsagePanel.form +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextUsagePanel.form @@ -2,11 +2,17 @@ - - + + + + + + + + - + @@ -24,30 +30,28 @@ - - + - - + - + - + - + diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextUsagePanel.java b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextUsagePanel.java index 4a96dfcffd..c3c74da190 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextUsagePanel.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextUsagePanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2020 Basis Technology Corp. + * Copyright 2020-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.contentviewers.contextviewer; import java.util.ArrayList; import java.util.List; +import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerDefaults; import org.sleuthkit.autopsy.directorytree.DirectoryTreeTopComponent; import org.sleuthkit.datamodel.BlackboardArtifact; import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT; @@ -74,8 +75,10 @@ public final class ContextUsagePanel extends javax.swing.JPanel implements Conte jUsageNameLabel = new javax.swing.JLabel(); jUsageTextLabel = new javax.swing.JLabel(); - setBackground(new java.awt.Color(255, 255, 255)); - setPreferredSize(new java.awt.Dimension(495, 75)); + setBackground(ContentViewerDefaults.getPanelBackground()); + setMaximumSize(new java.awt.Dimension(32767, 55)); + setMinimumSize(new java.awt.Dimension(300, 55)); + setPreferredSize(new java.awt.Dimension(495, 55)); org.openide.awt.Mnemonics.setLocalizedText(jUsageGoToResultButton, org.openide.util.NbBundle.getMessage(ContextUsagePanel.class, "ContextUsagePanel.jUsageGoToResultButton.text")); // NOI18N jUsageGoToResultButton.addActionListener(new java.awt.event.ActionListener() { @@ -93,25 +96,23 @@ public final class ContextUsagePanel extends javax.swing.JPanel implements Conte layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addGap(50, 50, 50) .addComponent(jUsageNameLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(jUsageTextLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 240, Short.MAX_VALUE) - .addGap(36, 36, 36)) + .addComponent(jUsageTextLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 420, Short.MAX_VALUE)) .addGroup(layout.createSequentialGroup() - .addGap(90, 90, 90) + .addGap(40, 40, 40) .addComponent(jUsageGoToResultButton) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap(275, javax.swing.GroupLayout.PREFERRED_SIZE)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addGap(2, 2, 2) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jUsageTextLabel) .addComponent(jUsageNameLabel, javax.swing.GroupLayout.Alignment.TRAILING)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jUsageGoToResultButton)) + .addComponent(jUsageGoToResultButton) + .addGap(0, 11, Short.MAX_VALUE)) ); }// //GEN-END:initComponents diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.form b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.form index 01c484ba9e..47c452eccb 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.form +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.form @@ -4,38 +4,19 @@ - - + + - - - - - - - - - - - - - - - - - - - + + - - - - + + @@ -50,38 +31,19 @@ - - + + - - - - - - - - - - - - - - - - - - - + + - - - - + + @@ -95,31 +57,9 @@ - - - - - - - - - - - - - - - - - - - - - - - - + + @@ -127,6 +67,9 @@ + + + @@ -137,11 +80,8 @@ - - - - + @@ -171,8 +111,8 @@ - - + + diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.java index bfa0cfc3e9..eae47348d2 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 Basis Technology Corp. + * Copyright 2019-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.contentviewers.contextviewer; import java.awt.Component; +import java.awt.Insets; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -28,12 +29,14 @@ import java.util.Map; import java.util.logging.Level; import javax.swing.BoxLayout; import static javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED; +import javax.swing.border.EmptyBorder; import org.apache.commons.lang.StringUtils; import org.openide.nodes.Node; import org.openide.util.NbBundle; import org.openide.util.lookup.ServiceProvider; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerDefaults; import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.AbstractFile; @@ -55,6 +58,10 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte private static final Logger logger = Logger.getLogger(ContextViewer.class.getName()); private static final int ARTIFACT_STR_MAX_LEN = 1024; private static final int ATTRIBUTE_STR_MAX_LEN = 200; + + private final static Insets FIRST_HEADER_INSETS = new Insets(0, 0, 0, 0); + private final static Insets HEADER_INSETS = new Insets(ContentViewerDefaults.getSectionSpacing(), 0, ContentViewerDefaults.getLineSpacing(), 0); + private final static Insets DATA_ROW_INSETS = new Insets(0, ContentViewerDefaults.getSectionIndent(), ContentViewerDefaults.getLineSpacing(), 0); // defines a list of artifacts that provide context for a file private static final List CONTEXT_ARTIFACTS = new ArrayList<>(); @@ -91,75 +98,30 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte javax.swing.JLabel jUnknownLabel = new javax.swing.JLabel(); jScrollPane = new javax.swing.JScrollPane(); - jSourcePanel.setBackground(javax.swing.UIManager.getDefaults().getColor("window")); + jSourcePanel.setBorder(new EmptyBorder(FIRST_HEADER_INSETS)); + jSourcePanel.setLayout(new javax.swing.BoxLayout(jSourcePanel, javax.swing.BoxLayout.PAGE_AXIS)); - jSourceLabel.setFont(jSourceLabel.getFont().deriveFont(jSourceLabel.getFont().getStyle() | java.awt.Font.BOLD, jSourceLabel.getFont().getSize()+1)); + jSourceLabel.setFont(ContentViewerDefaults.getHeaderFont()); org.openide.awt.Mnemonics.setLocalizedText(jSourceLabel, org.openide.util.NbBundle.getMessage(ContextViewer.class, "ContextViewer.jSourceLabel.text")); // NOI18N + jSourcePanel.add(jSourceLabel); - javax.swing.GroupLayout jSourcePanelLayout = new javax.swing.GroupLayout(jSourcePanel); - jSourcePanel.setLayout(jSourcePanelLayout); - jSourcePanelLayout.setHorizontalGroup( - jSourcePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jSourcePanelLayout.createSequentialGroup() - .addGap(40, 40, 40) - .addComponent(jSourceLabel) - .addContainerGap(304, Short.MAX_VALUE)) + jUsagePanel.setBorder(new EmptyBorder(HEADER_INSETS)); + jUsagePanel.setLayout(new javax.swing.BoxLayout(jUsagePanel, javax.swing.BoxLayout.PAGE_AXIS)); + + jUsageLabel.setFont(ContentViewerDefaults.getHeaderFont() ); - jSourcePanelLayout.setVerticalGroup( - jSourcePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jSourcePanelLayout.createSequentialGroup() - .addGap(5, 5, 5) - .addComponent(jSourceLabel) - .addGap(2, 2, 2)) - ); - - jUsagePanel.setBackground(javax.swing.UIManager.getDefaults().getColor("window")); - - jUsageLabel.setFont(jUsageLabel.getFont().deriveFont(jUsageLabel.getFont().getStyle() | java.awt.Font.BOLD, jUsageLabel.getFont().getSize()+1)); org.openide.awt.Mnemonics.setLocalizedText(jUsageLabel, org.openide.util.NbBundle.getMessage(ContextViewer.class, "ContextViewer.jUsageLabel.text")); // NOI18N + jUsagePanel.add(jUsageLabel); - javax.swing.GroupLayout jUsagePanelLayout = new javax.swing.GroupLayout(jUsagePanel); - jUsagePanel.setLayout(jUsagePanelLayout); - jUsagePanelLayout.setHorizontalGroup( - jUsagePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jUsagePanelLayout.createSequentialGroup() - .addGap(40, 40, 40) - .addComponent(jUsageLabel) - .addContainerGap(298, Short.MAX_VALUE)) - ); - jUsagePanelLayout.setVerticalGroup( - jUsagePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jUsagePanelLayout.createSequentialGroup() - .addGap(2, 2, 2) - .addComponent(jUsageLabel) - .addGap(2, 2, 2)) - ); - - jUnknownPanel.setBackground(new java.awt.Color(255, 255, 255)); + jUnknownPanel.setLayout(new javax.swing.BoxLayout(jUnknownPanel, javax.swing.BoxLayout.PAGE_AXIS)); org.openide.awt.Mnemonics.setLocalizedText(jUnknownLabel, org.openide.util.NbBundle.getMessage(ContextViewer.class, "ContextViewer.jUnknownLabel.text")); // NOI18N + jUnknownLabel.setBorder(new EmptyBorder(DATA_ROW_INSETS)); + jUnknownPanel.add(jUnknownLabel); - javax.swing.GroupLayout jUnknownPanelLayout = new javax.swing.GroupLayout(jUnknownPanel); - jUnknownPanel.setLayout(jUnknownPanelLayout); - jUnknownPanelLayout.setHorizontalGroup( - jUnknownPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jUnknownPanelLayout.createSequentialGroup() - .addGap(50, 50, 50) - .addComponent(jUnknownLabel) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - ); - jUnknownPanelLayout.setVerticalGroup( - jUnknownPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jUnknownPanelLayout.createSequentialGroup() - .addGap(2, 2, 2) - .addComponent(jUnknownLabel) - .addGap(2, 2, 2)) - ); + setPreferredSize(new java.awt.Dimension(0, 0)); - setBackground(new java.awt.Color(255, 255, 255)); - setPreferredSize(new java.awt.Dimension(495, 358)); - - jScrollPane.setBackground(new java.awt.Color(255, 255, 255)); + jScrollPane.setPreferredSize(new java.awt.Dimension(16, 16)); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); @@ -275,13 +237,17 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte } } javax.swing.JPanel contextContainer = new javax.swing.JPanel(); - contextContainer.add(jSourcePanel); contextContainer.setLayout(new BoxLayout(contextContainer, BoxLayout.Y_AXIS)); + contextContainer.setBorder(new EmptyBorder(ContentViewerDefaults.getPanelInsets())); + + contextContainer.add(jSourcePanel); + if (contextSourcePanels.isEmpty()) { contextContainer.add(jUnknownPanel); } else { for (javax.swing.JPanel sourcePanel : contextSourcePanels) { contextContainer.add(sourcePanel); + contextContainer.setAlignmentX(0); } } contextContainer.add(jUsagePanel); @@ -290,10 +256,11 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte } else { for (javax.swing.JPanel usagePanel : contextUsagePanels) { contextContainer.add(usagePanel); + contextContainer.setAlignmentX(0); } } - contextContainer.setBackground(javax.swing.UIManager.getDefaults().getColor("window")); + contextContainer.setBackground(ContentViewerDefaults.getPanelBackground()); contextContainer.setEnabled(foundASource); contextContainer.setVisible(foundASource); jScrollPane.getViewport().setView(contextContainer); @@ -346,6 +313,8 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte String sourceName = Bundle.ContextViewer_attachmentSource(); String sourceText = msgArtifactToAbbreviatedString(associatedArtifact); ContextSourcePanel sourcePanel = new ContextSourcePanel(sourceName, sourceText, associatedArtifact, dateTime); + sourcePanel.setBorder(new EmptyBorder(DATA_ROW_INSETS)); + sourcePanel.setAlignmentX(0); contextSourcePanels.add(sourcePanel); } else if (BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID() == associatedArtifact.getArtifactTypeID() @@ -353,18 +322,24 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte String sourceName = Bundle.ContextViewer_downloadSource(); String sourceText = webDownloadArtifactToString(associatedArtifact); ContextSourcePanel sourcePanel = new ContextSourcePanel(sourceName, sourceText, associatedArtifact, dateTime); + sourcePanel.setBorder(new EmptyBorder(DATA_ROW_INSETS)); + sourcePanel.setAlignmentX(0); contextSourcePanels.add(sourcePanel); } else if (BlackboardArtifact.ARTIFACT_TYPE.TSK_RECENT_OBJECT.getTypeID() == associatedArtifact.getArtifactTypeID()) { String sourceName = Bundle.ContextViewer_recentDocs(); String sourceText = recentDocArtifactToString(associatedArtifact); - ContextUsagePanel usagePanel = new ContextUsagePanel(sourceName, sourceText, associatedArtifact, dateTime); + ContextUsagePanel usagePanel = new ContextUsagePanel(sourceName, sourceText, associatedArtifact, dateTime); + usagePanel.setBorder(new EmptyBorder(DATA_ROW_INSETS)); + usagePanel.setAlignmentX(0); contextUsagePanels.add(usagePanel); } else if (BlackboardArtifact.ARTIFACT_TYPE.TSK_PROG_RUN.getTypeID() == associatedArtifact.getArtifactTypeID()) { String sourceName = Bundle.ContextViewer_programExecution(); String sourceText = programExecArtifactToString(associatedArtifact); - ContextUsagePanel usagePanel = new ContextUsagePanel(sourceName, sourceText, associatedArtifact, dateTime); + ContextUsagePanel usagePanel = new ContextUsagePanel(sourceName, sourceText, associatedArtifact, dateTime); + usagePanel.setBorder(new EmptyBorder(DATA_ROW_INSETS)); + usagePanel.setAlignmentX(0); contextUsagePanels.add(usagePanel); } diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/layout/ContentViewerDefaults.java b/Core/src/org/sleuthkit/autopsy/contentviewers/layout/ContentViewerDefaults.java new file mode 100644 index 0000000000..65023b9110 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/layout/ContentViewerDefaults.java @@ -0,0 +1,167 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 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.contentviewers.layout; + +import java.awt.Font; +import java.awt.Insets; +import java.awt.Toolkit; +import java.awt.Color; +import javax.swing.UIManager; + +/** + * Default values for layout of content values. + */ +public class ContentViewerDefaults { + + private static final Font DEFAULT_FONT = UIManager.getDefaults().getFont("Label.font"); + + // based on https://stackoverflow.com/questions/5829703/java-getting-a-font-with-a-specific-height-in-pixels/26564924#26564924 + private static final Double PT_TO_PX = Toolkit.getDefaultToolkit().getScreenResolution() / 72.0; + + private static final int DEFAULT_FONT_PX = (int) Math.round(DEFAULT_FONT.getSize() * PT_TO_PX); + + private static final Font SUB_HEADER_FONT = DEFAULT_FONT.deriveFont(Font.BOLD); + + private static final Font HEADER_FONT = DEFAULT_FONT.deriveFont(Font.BOLD, DEFAULT_FONT.getSize() + 2); + + private static final Font MESSAGE_FONT = DEFAULT_FONT.deriveFont(Font.ITALIC); + + private static final Font MONOSPACED_FONT = new Font(Font.MONOSPACED, Font.PLAIN, DEFAULT_FONT.getSize()); + + private static final Insets DEFAULT_PANEL_INSETS = UIManager.getDefaults().getInsets("TextPane.margin"); + + private static final int DEFAULT_INDENT = DEFAULT_FONT_PX; + private static final int DEFAULT_SECTION_SPACING = DEFAULT_FONT_PX; + + private static final int DEFAULT_COLUMN_SPACING = (int) Math.round((double) DEFAULT_FONT_PX / 3); + + private static final int DEFAULT_LINE_SPACING = (int) Math.round((double) DEFAULT_FONT_PX / 5); + + private static final Color DEFAULT_BACKGROUND = UIManager.getColor("Panel.background"); + + /** + * Returns the horizontal spacing between columns in a table in pixels. + * + * @return The horizontal spacing between columns in a table in pixels. + */ + public static int getColumnSpacing() { + return DEFAULT_COLUMN_SPACING; + } + + /** + * Returns the default font to be used. + * + * @return the default font to be used. + */ + public static Font getFont() { + return DEFAULT_FONT; + } + + /** + * Returns the font to be displayed for messages. + * + * @return The font to be displayed for messages. + */ + public static Font getMessageFont() { + return MESSAGE_FONT; + } + + /** + * Returns the font to be displayed for messages. + * + * @return The font to be displayed for messages. + */ + public static Font getHeaderFont() { + return HEADER_FONT; + } + + /** + * Returns the font to be displayed for sub headers. + * + * @return The font to be displayed for sub headers. + */ + public static Font getSubHeaderFont() { + return SUB_HEADER_FONT; + } + + /** + * Returns the font to be used for normal monospace. + * + * @return The font to be used for normal monospace. + */ + public static Font getMonospacedFont() { + return MONOSPACED_FONT; + } + + /** + * Returns the insets of the content within the parent content viewer panel. + * + * @return The insets of the content within the parent content viewer panel. + */ + public static Insets getPanelInsets() { + return DEFAULT_PANEL_INSETS; + } + + /** + * Returns the size in pixels that sections should be indented. + * + * @return The size in pixels that sections should be indented. + */ + public static Integer getSectionIndent() { + return DEFAULT_INDENT; + } + + /** + * Returns the spacing between sections in pixels. + * + * @return The spacing between sections in pixels. + */ + public static Integer getSectionSpacing() { + return DEFAULT_SECTION_SPACING; + } + + /** + * Returns the spacing between lines of text in pixels. + * + * @return The spacing between lines of text in pixels. + */ + public static Integer getLineSpacing() { + return DEFAULT_LINE_SPACING; + } + + /** + * Returns the color to be used as the background of the panel. + * + * @return The color to be used as the background of the panel. + */ + public static Color getPanelBackground() { + return DEFAULT_BACKGROUND; + } + + /** + * Returns the ratio of point size to pixel size for the user's screen + * resolution. + * + * @return The ratio of point size to pixel size for the user's screen + * resolution. + */ + public static Double getPtToPx() { + return PT_TO_PX; + } +} diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/layout/ContentViewerHtmlStyles.java b/Core/src/org/sleuthkit/autopsy/contentviewers/layout/ContentViewerHtmlStyles.java new file mode 100644 index 0000000000..17632dc802 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/layout/ContentViewerHtmlStyles.java @@ -0,0 +1,194 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 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.contentviewers.layout; + +import java.awt.Font; +import javax.swing.JTextPane; +import javax.swing.text.EditorKit; +import javax.swing.text.html.HTMLEditorKit; +import javax.swing.text.html.StyleSheet; + +/** + * The style sheet an class names to be used with content viewers using html + * rendering. + */ +public class ContentViewerHtmlStyles { + + // html stylesheet classnames for components + private static final String CLASS_PREFIX = ContentViewerHtmlStyles.class.getSimpleName(); + + private static final String HEADER_CLASSNAME = CLASS_PREFIX + "header"; + private static final String SUB_HEADER_CLASSNAME = CLASS_PREFIX + "subHeader"; + + private static final String MESSAGE_CLASSNAME = CLASS_PREFIX + "message"; + private static final String TEXT_CLASSNAME = CLASS_PREFIX + "text"; + private static final String MONOSPACED_CLASSNAME = CLASS_PREFIX + "monospaced"; + private static final String INDENTED_CLASSNAME = CLASS_PREFIX + "indent"; + private static final String SPACED_SECTION_CLASSNAME = CLASS_PREFIX + "spacedSection"; + private static final String KEY_COLUMN_TD_CLASSNAME = CLASS_PREFIX + "keyKolumn"; + + private static final Font DEFAULT_FONT = ContentViewerDefaults.getFont(); + private static final Font MESSAGE_FONT = ContentViewerDefaults.getMessageFont(); + private static final Font HEADER_FONT = ContentViewerDefaults.getHeaderFont(); + private static final Font SUB_HEADER_FONT = ContentViewerDefaults.getSubHeaderFont(); + private static final Font MONOSPACED_FONT = ContentViewerDefaults.getMonospacedFont(); + + // additional styling for components + private static final String STYLE_SHEET_RULE + = String.format(" .%s { font-family: %s; font-size: %dpt;font-style:italic; margin: 0px; padding: 0px 0px %dpt 0px; } ", + MESSAGE_CLASSNAME, MESSAGE_FONT.getFamily(), MESSAGE_FONT.getSize(), pxToPt(ContentViewerDefaults.getLineSpacing())) + + String.format(" .%s { font-family: %s; font-size: %dpt; font-weight: bold; margin: 0px; padding: 0px 0px %dpt 0px; } ", + HEADER_CLASSNAME, HEADER_FONT.getFamily(), HEADER_FONT.getSize(), pxToPt(ContentViewerDefaults.getLineSpacing())) + + String.format(" .%s { font-family: %s; font-size: %dpt; font-weight: bold; margin: 0px; padding: 0px 0px %dpt 0px; } ", + SUB_HEADER_CLASSNAME, SUB_HEADER_FONT.getFamily(), SUB_HEADER_FONT.getSize(), pxToPt(ContentViewerDefaults.getLineSpacing())) + + String.format(" .%s { font-family: %s; font-size: %dpt; margin: 0px; padding: 0px 0px %dpt 0px; } ", + TEXT_CLASSNAME, DEFAULT_FONT.getFamily(), DEFAULT_FONT.getSize(), pxToPt(ContentViewerDefaults.getLineSpacing())) + + String.format(" .%s { font-family: %s; font-size: %dpt; margin: 0px; padding: 0px 0px %dpt 0px; } ", + MONOSPACED_CLASSNAME, Font.MONOSPACED, MONOSPACED_FONT.getSize(), pxToPt(ContentViewerDefaults.getLineSpacing())) + + String.format(" .%s { padding-left: %dpt } ", + INDENTED_CLASSNAME, pxToPt(ContentViewerDefaults.getSectionIndent())) + + String.format(" .%s { padding-top: %dpt } ", + SPACED_SECTION_CLASSNAME, pxToPt(ContentViewerDefaults.getSectionSpacing())) + + String.format(" .%s { padding-right: %dpt } ", + KEY_COLUMN_TD_CLASSNAME, pxToPt(ContentViewerDefaults.getColumnSpacing())); + + private static final StyleSheet STYLE_SHEET = new StyleSheet(); + + static { + // add the style rule to the style sheet. + STYLE_SHEET.addRule(STYLE_SHEET_RULE); + } + + /** + * Converts pixel size to point size. The html rendering seems more + * consistent with point size versus pixel size. + * + * @param px The pixel size. + * + * @return The point size. + */ + private static int pxToPt(int px) { + return (int) Math.round(((double) px) / ContentViewerDefaults.getPtToPx()); + } + + /** + * Returns the class name to use for header text. + * + * @return The class name to use for header text. + */ + public static String getHeaderClassName() { + return HEADER_CLASSNAME; + } + + /** + * Returns the class name to use for sub header text. + * + * @return The class name to use for sub header text. + */ + public static String getSubHeaderClassName() { + return SUB_HEADER_CLASSNAME; + } + + /** + * Returns the class name to use for message text. + * + * @return The class name to use for message text. + */ + public static String getMessageClassName() { + return MESSAGE_CLASSNAME; + } + + /** + * Returns the class name to use for regular text. + * + * @return The class name to use for regular text. + */ + public static String getTextClassName() { + return TEXT_CLASSNAME; + } + + /** + * Returns the class name to use for monospaced text. + * + * @return The class name to use for monospaced text. + */ + public static String getMonospacedClassName() { + return MONOSPACED_CLASSNAME; + } + + /** + * Returns the class name to use for an indented (left padding) section. + * + * @return The class name to use for an indented (left padding) section. + */ + public static String getIndentedClassName() { + return INDENTED_CLASSNAME; + } + + /** + * Returns the class name to use for a section with spacing (top padding) + * section. + * + * @return The class name to use for a section with spacing (top padding) + * section. + */ + public static String getSpacedSectionClassName() { + return SPACED_SECTION_CLASSNAME; + } + + /** + * Returns the class name to use for a key column with right spacing (right + * padding). + * + * @return The class name to use for a key column with right spacing (right + * padding). + */ + public static String getKeyColumnClassName() { + return KEY_COLUMN_TD_CLASSNAME; + } + + /** + * If the textPane has an HTMLEditorKit, specifies the + * ContentViewerHTMLStyles styles to use refreshing the styles. + * + * @param textPane The text pane. + */ + public static void setStyles(JTextPane textPane) { + EditorKit editorKit = textPane.getEditorKit(); + if (editorKit instanceof HTMLEditorKit) { + ((HTMLEditorKit) editorKit).setStyleSheet(STYLE_SHEET); + } + } + + /** + * Sets up a JTextPane for html rendering using the css class names + * specified in this class. + * + * @param textPane The JTextPane to set up for content viewer html + * rendering. + */ + public static void setupHtmlJTextPane(JTextPane textPane) { + textPane.setContentType("text/html;charset=UTF-8"); //NON-NLS + HTMLEditorKit kit = new HTMLEditorKit(); + textPane.setEditorKit(kit); + kit.setStyleSheet(STYLE_SHEET); + textPane.setMargin(ContentViewerDefaults.getPanelInsets()); + textPane.setBackground(ContentViewerDefaults.getPanelBackground()); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/Bundle_ja.properties new file mode 100644 index 0000000000..9b0e640012 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/Bundle_ja.properties @@ -0,0 +1,21 @@ +#Mon Jun 14 12:23:19 UTC 2021 +OsAccountDataPanel_administrator_title=\u7ba1\u7406\u8005 +OsAccountDataPanel_basic_address=\u4f4f\u6240 +OsAccountDataPanel_basic_admin=\u7ba1\u7406\u8005 +OsAccountDataPanel_basic_creationDate=\u4f5c\u6210\u65e5 +OsAccountDataPanel_basic_fullname=\u6c0f\u540d +OsAccountDataPanel_basic_login=\u30ed\u30b0\u30a4\u30f3 +OsAccountDataPanel_basic_title=\u57fa\u672c\u30d7\u30ed\u30d1\u30c6\u30a3 +OsAccountDataPanel_basic_type=\u30bf\u30a4\u30d7 +OsAccountDataPanel_data_accessed_title=\u524d\u56de\u306e\u30ed\u30b0\u30a4\u30f3 +OsAccountDataPanel_host_count_title=\u30ed\u30b0\u30a4\u30f3\u6570 +OsAccountDataPanel_host_section_title={0} \u8a73\u7d30 +OsAccountDataPanel_realm_address=\u4f4f\u6240 +OsAccountDataPanel_realm_confidence=\u4fe1\u983c\u5ea6 +OsAccountDataPanel_realm_name=\u540d\u524d +OsAccountDataPanel_realm_scope=\u30b9\u30b3\u30fc\u30d7 +OsAccountDataPanel_realm_title=\u5206\u91ce\u30d7\u30ed\u30d1\u30c6\u30a3 +OsAccountDataPanel_realm_unknown=\u4e0d\u660e +OsAccountViewer_title=OS\u30a2\u30ab\u30a6\u30f3\u30c8 +OsAccountViewer_tooltip=\u9078\u629e\u3057\u305f\u30ce\u30fc\u30c9\u306b\u95a2\u9023\u3059\u308b\u30aa\u30da\u30ec\u30fc\u30c6\u30a3\u30f3\u30b0\u30b7\u30b9\u30c6\u30e0\u30a2\u30ab\u30a6\u30f3\u30c8\u306e\u30d3\u30e5\u30fc\u30a2\u3002 +TableDataPanel.titleLabel.text=\u79f0\u53f7 diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountDataPanel.java b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountDataPanel.java index 2c88660cb0..3ab02ed4d7 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountDataPanel.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountDataPanel.java @@ -19,7 +19,6 @@ package org.sleuthkit.autopsy.contentviewers.osaccount; import java.awt.BorderLayout; -import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; @@ -38,8 +37,10 @@ import javax.swing.Box; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.SwingWorker; +import javax.swing.border.EmptyBorder; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerDefaults; import org.sleuthkit.autopsy.contentviewers.osaccount.SectionData.RowData; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.DataSource; @@ -61,7 +62,11 @@ public class OsAccountDataPanel extends JPanel { private static final int KEY_COLUMN = 0; private static final int VALUE_COLUMN = 1; - + + private final static Insets FIRST_HEADER_INSETS = new Insets(0, 0, 0, 0); + private final static Insets HEADER_INSETS = new Insets(ContentViewerDefaults.getSectionSpacing(), 0, ContentViewerDefaults.getLineSpacing(), 0); + private final static Insets VALUE_COLUMN_INSETS = new Insets(0, ContentViewerDefaults.getColumnSpacing(), ContentViewerDefaults.getLineSpacing(), 0); + private final static Insets KEY_COLUMN_INSETS = new Insets(0, ContentViewerDefaults.getSectionIndent(), ContentViewerDefaults.getLineSpacing(), 0); private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MMM dd yyyy", US); private PanelDataFetcher dataFetcher = null; @@ -76,6 +81,7 @@ public class OsAccountDataPanel extends JPanel { */ private void initialize() { this.setLayout(new GridBagLayout()); + this.setBorder(new EmptyBorder(ContentViewerDefaults.getPanelInsets())); } /** @@ -269,7 +275,7 @@ public class OsAccountDataPanel extends JPanel { private void addTitle(String title, int row) { JLabel label = new JLabel(title); // Make the title bold. - label.setFont(label.getFont().deriveFont(Font.BOLD)); + label.setFont(ContentViewerDefaults.getHeaderFont()); add(label, getTitleContraints(row)); } @@ -312,7 +318,9 @@ public class OsAccountDataPanel extends JPanel { constraints.anchor = GridBagConstraints.NORTHWEST; constraints.fill = GridBagConstraints.HORIZONTAL; constraints.weightx = 1; - constraints.insets = new Insets(5, 5, 5, 9); + constraints.insets = (row == 0) + ? FIRST_HEADER_INSETS + : HEADER_INSETS; return constraints; } @@ -332,7 +340,7 @@ public class OsAccountDataPanel extends JPanel { constraints.gridwidth = 1; // The title goes across the other columns constraints.gridheight = 1; constraints.anchor = GridBagConstraints.WEST; - constraints.insets = new Insets(0, 13, 5, 5); + constraints.insets = KEY_COLUMN_INSETS; return constraints; } @@ -352,8 +360,8 @@ public class OsAccountDataPanel extends JPanel { constraints.gridwidth = 1; // The title goes across the other columns constraints.gridheight = 1; constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.insets = VALUE_COLUMN_INSETS; constraints.weightx = 1; - constraints.insets = new Insets(0, 5, 5, 5); return constraints; } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutoWrappingJTextPane.java b/Core/src/org/sleuthkit/autopsy/corecomponents/AutoWrappingJTextPane.java index 1e4c1f4c63..652034dacc 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutoWrappingJTextPane.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutoWrappingJTextPane.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 Basis Technology Corp. + * Copyright 2019-2021 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.corecomponents; +import java.text.MessageFormat; import javax.swing.JTextPane; import javax.swing.SizeRequirements; import javax.swing.text.Element; @@ -27,6 +28,8 @@ import javax.swing.text.ViewFactory; import javax.swing.text.html.HTMLEditorKit; import javax.swing.text.html.InlineView; import javax.swing.text.html.ParagraphView; +import javax.swing.text.html.StyleSheet; +import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerDefaults; import org.sleuthkit.autopsy.coreutils.EscapeUtil; /** @@ -96,9 +99,15 @@ public class AutoWrappingJTextPane extends JTextPane { this.setEditorKit(editorKit); } + + @Override public void setText(String text) { - super.setText("
" + EscapeUtil.escapeHtml(text) + "
"); + // setting the text format with style to avoid problems with overridden styles. + String style = String.format("font-family: %s; font-size: %dpt; margin: 0px; padding: 0px 0px %dpx 0px;", + ContentViewerDefaults.getFont().getFamily(), ContentViewerDefaults.getFont().getSize(), ContentViewerDefaults.getLineSpacing()); + + super.setText(MessageFormat.format("
{1}
", style, EscapeUtil.escapeHtml(text))); } } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle_ja.properties index 1c6c191439..1b5307c698 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle_ja.properties @@ -1,4 +1,4 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Mon Jun 14 12:23:19 UTC 2021 AboutWindowPanel.actVerboseLogging.text=\u8a73\u7d30\u30ed\u30ae\u30f3\u30b0\u3092\u30a2\u30af\u30c6\u30a3\u30d6\u5316 AddExternalViewerRulePanel.browseButton.text=\u53c2\u7167 AddExternalViewerRulePanel.exePathLabel.text=\u3053\u306e\u30bf\u30a4\u30d7\u307e\u305f\u306f\u62e1\u5f35\u5b50\u306e\u30d5\u30a1\u30a4\u30eb\u306b\u4f7f\u7528\u3059\u308b\u30d7\u30ed\u30b0\u30e9\u30e0\u306e\u30d1\u30b9 @@ -41,12 +41,18 @@ AutopsyOptionsPanel.runtimePanel.border.title=\u30e9\u30f3\u30bf\u30a4\u30e0 AutopsyOptionsPanel.sizingTextPane.text=\u9ad8DPI\u30b7\u30b9\u30c6\u30e0\u3067\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u30ca\u30d3\u30b2\u30fc\u30c8\u304c\u96e3\u3057\u3044\u5834\u5408\u306f\u3001\u6b21\u306e\u5909\u66f4\u3092\u884c\u3063\u3066\u304f\u3060\u3055\u3044\u3002\n\n1.\u30c7\u30b9\u30af\u30c8\u30c3\u30d7\u3001\u30b9\u30bf\u30fc\u30c8\u30e1\u30cb\u30e5\u30fc\u306a\u3069\u306e\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u30a2\u30a4\u30b3\u30f3\u3092\u53f3\u30af\u30ea\u30c3\u30af\n2.\u30d7\u30ed\u30d1\u30c6\u30a3\u3092\u9078\u629e\n3. [\u4e92\u63db\u6027]\u30bf\u30d6\u306b\u79fb\u52d5\n4. [\u9ad8DPI\u8a2d\u5b9a\u306e\u5909\u66f4]\u30dc\u30bf\u30f3\u3092\u30af\u30ea\u30c3\u30af\n5. [\u9ad8DPI\u30b9\u30b1\u30fc\u30ea\u30f3\u30b0\u52d5\u4f5c\u3092\u5909\u66f4]\u3092\u9078\u629e\n6.\u300c\u30b9\u30b1\u30fc\u30ea\u30f3\u30b0\u306e\u5b9f\u884c\uff1a\u300d\u30c9\u30ed\u30c3\u30d7\u30c0\u30a6\u30f3\u30dc\u30c3\u30af\u30b9\u3092\u300c\u30b7\u30b9\u30c6\u30e0\u300d\u306b\u5909\u66f4\u3057\u307e\u3059\u3002\n7.Autopsy\u3092\u518d\u5b9f\u884c AutopsyOptionsPanel.solrJVMHeapWarning.text=\u6ce8\: \u3053\u308c\u3092\u3042\u307e\u308a\u306b\u3082\u5927\u304d\u304f\u8a2d\u5b9a\u3059\u308b\u3068\u3001\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u5168\u4f53\u306b\u5f71\u97ff\u3059\u308b\u3053\u3068\u304c\u3042\u308a\u307e\u3059\u3002 AutopsyOptionsPanel.specifyLogoRB.text=\u30ed\u30b4\u3092\u6307\u5b9a +AutopsyOptionsPanel.tempCaseRadio.text=\u30b1\u30fc\u30b9\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306e\u4e00\u6642\u30d5\u30a9\u30eb\u30c0 +AutopsyOptionsPanel.tempCustomRadio.text=\u30ab\u30b9\u30bf\u30e0 AutopsyOptionsPanel.tempDirectoryBrowseButton.text=\u30d6\u30e9\u30a6\u30ba AutopsyOptionsPanel.tempDirectoryPanel.AccessibleContext.accessibleName=\u4e00\u6642\u30d5\u30a9\u30eb\u30c0 -AutopsyOptionsPanel.tempDirectoryPanel.border.title=\u4e00\u6642\u30d5\u30a9\u30eb\u30c0 +AutopsyOptionsPanel.tempDirectoryPanel.border.title=\u30eb\u30fc\u30c8\u4e00\u6642\u30c7\u30a3\u30ec\u30af\u30c8\u30ea AutopsyOptionsPanel.tempDirectoryPanel.name=\u4e00\u6642\u30d5\u30a9\u30eb\u30c0 AutopsyOptionsPanel.tempDirectoryWarningLabel.text=\u4e00\u6642\u30d5\u30a9\u30eb\u30c0\u3092\u5909\u66f4\u3059\u308b\u306b\u306f\u30b1\u30fc\u30b9\u3092\u9589\u3058\u3066\u4e0b\u3055\u3044\u3002 +AutopsyOptionsPanel.tempLocalRadio.text=\u30ed\u30fc\u30ab\u30eb\u4e00\u6642\u30c7\u30a3\u30ec\u30af\u30c8\u30ea +AutopsyOptionsPanel.tempOnCustomNoPath.text=\u30ab\u30b9\u30bf\u30e0\u30eb\u30fc\u30c8\u306e\u4e00\u6642\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fb\u30d1\u30b9\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 AutopsyOptionsPanel.totalMemoryLabel.text=\u5408\u8a08\u30b7\u30b9\u30c6\u30e0\u30e1\u30e2\u30ea\u30fc\: +AutopsyOptionsPanel_storeTempDir_onChoiceError_description=\u4e00\u6642\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u9078\u629e\u306e\u66f4\u65b0\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +AutopsyOptionsPanel_storeTempDir_onChoiceError_title=\u4e00\u6642\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u9078\u629e\u306e\u4fdd\u5b58\u30a8\u30e9\u30fc AutopsyOptionsPanel_storeTempDir_onError_description=\u30b7\u30b9\u30c6\u30e0\u4e00\u6642\u30d5\u30a9\u30eb\u30c0{0}\u3092\u4f5c\u6210\u3059\u308b\u3068\u304d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 AutopsyOptionsPanel_storeTempDir_onError_title=\u4e00\u6642\u30d5\u30a9\u30eb\u30c0\u4fdd\u5b58\u306b\u5931\u6557\u3057\u307e\u3057\u305f AutopsyOptionsPanel_tempDirectoryBrowseButtonActionPerformed_onInvalidPath_description=\u6307\u5b9a\u3055\u308c\u305f\u30d1\u30b9\u5185\u306b\u4e00\u6642\u30d5\u30a9\u30eb\u30c0\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\uff1a{0} @@ -241,6 +247,7 @@ MultiUserSettingsPanel.validationErrMsg.invalidSolr4ServerPort=Solr4\u30b5\u30fc MultiUserSettingsPanel.validationErrMsg.invalidZkServerHostName=ZooKeeper\u30b5\u30fc\u30d0\u30fc\u306e\u30db\u30b9\u30c8\u540d\u304c\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u305b\u3093 MultiUserSettingsPanel.validationErrMsg.invalidZkServerPort=ZooKeeper\u30b5\u30fc\u30d0\u30fc\u306e\u30dd\u30fc\u30c8\u756a\u53f7\u304c\u7121\u52b9\u3067\u3059 MultiUserSettingsPanel.validationErrMsg.solrNotConfigured=Solr8\u3068Solr4\u30b5\u30fc\u30d0\u30fc\u306e\u3044\u305a\u308c\u304b\u3092\u69cb\u6210\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059 +MultiUserSettingsPanel_Close_Case_To_Modify=\u8a2d\u5b9a\u3092\u5909\u66f4\u3059\u308b\u306b\u306f\u30b1\u30fc\u30b9\u3092\u9589\u3058\u3066\u304f\u3060\u3055\u3044 OpenIDE-Module-Name=CoreComponents OptionsCategory_Keywords_General=Autopsy\u30aa\u30d7\u30b7\u30e7\u30f3 OptionsCategory_Keywords_Multi_User_Options=\u30de\u30eb\u30c1\u30e6\u30fc\u30b6\u30fc\u8a2d\u5b9a @@ -267,7 +274,6 @@ ViewPreferencesPanel.dataSourcesHideSlackCheckbox.text=\u30c7\u30fc\u30bf\u30bd\ ViewPreferencesPanel.displayTimeLabel.text=\u6642\u523b\u8868\u793a\u6642\: ViewPreferencesPanel.fileNameTranslationColumnCheckbox.text=\u7d50\u679c\u30d3\u30e5\u30fc\u30ef\u30fc\u306b\u30d5\u30a1\u30a4\u30eb\u540d\u7ffb\u8a33\u7528\u5217\u3092\u8ffd\u52a0 ViewPreferencesPanel.globalSettingsPanel.border.title=\u30b0\u30ed\u30fc\u30d0\u30eb\u8a2d\u5b9a -ViewPreferencesPanel.groupByDataSourceCheckbox.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u5225\u306b\u30b0\u30eb\u30fc\u30d7\u5316 ViewPreferencesPanel.hideKnownFilesLabel.text=\u6b21\u306e\u65e2\u77e5\u306e\u30d5\u30a1\u30a4\u30eb(NIST NSRL\u5185\u306e\u30d5\u30a1\u30a4\u30eb)\u3092\u975e\u8868\u793a\u306b\u3059\u308b\: ViewPreferencesPanel.hideOtherUsersTagsCheckbox.text=\u30c4\u30ea\u30fc\u5185\u306e\u30bf\u30b0\u9818\u57df ViewPreferencesPanel.hideOtherUsersTagsLabel.text=\u6b21\u306e\u305d\u306e\u4ed6\u306e\u30e6\u30fc\u30b6\u30fc\u306e\u30bf\u30b0\u3092\u975e\u8868\u793a\u306b\u3059\u308b\: @@ -277,6 +283,8 @@ ViewPreferencesPanel.keepCurrentViewerRadioButton.text=\u540c\u3058\u30d5\u30a1\ ViewPreferencesPanel.keepCurrentViewerRadioButton.toolTipText=\u305f\u3068\u3048\u3070\u3001JPEG\u9078\u629e\u6642\u306f16\u9032\u30d3\u30e5\u30fc\u306e\u307e\u307e\u306b\u3057\u307e\u3059\u3002 ViewPreferencesPanel.maxResultsLabel.text=\u30c6\u30fc\u30d6\u30eb\u3067\u8868\u793a\u3059\u308b\u6700\u5927\u7d50\u679c\u6570\: ViewPreferencesPanel.maxResultsLabel.toolTipText=\n\u3053\u306e\u5024\u30920 \u306b\u8a2d\u5b9a\u3059\u308b\u3068\u3001\u3059\u3079\u3066\u306e\u7d50\u679c\u304c\u7d50\u679c\u30c6\u30fc\u30d6\u30eb\u306b\u8868\u793a\u3055\u308c\u307e\u3059\u3002\n
\u3053\u306e\u5024\u30920 \u306b\u8a2d\u5b9a\u3059\u308b\u3068\u3001\u7d50\u679c\u6570\u304c\u591a\u3044\u5834\u5408UI\u306e\u5fdc\u7b54\u6027\u304c\u60aa\u304f\u306a\u308b\u3053\u3068\u304c\u3042\u308a\u307e\u3059 \u3002\n +ViewPreferencesPanel.radioGroupByDataType.text=\u30c7\u30fc\u30bf\u30fb\u30bf\u30a4\u30d7\u3067\u30b0\u30eb\u30fc\u30d7\u5316 +ViewPreferencesPanel.radioGroupByPersonHost.text=\u4eba/\u30db\u30b9\u30c8\u3067\u30b0\u30eb\u30fc\u30d7\u5316 ViewPreferencesPanel.scoColumnsCheckbox.text=S(\u30b9\u30b3\u30a2)\u3001C(\u30b3\u30e1\u30f3\u30c8)\u3001O(\u767a\u751f) ViewPreferencesPanel.scoColumnsLabel.text=\u6b21\u306e\u305f\u3081\u306e\u5217\u3092\u8ffd\u52a0\u3057\u306a\u3044\: ViewPreferencesPanel.scoColumnsWrapAroundText.text=\u975e\u8868\u793a\u306b\u3059\u308b\u3068\u8aad\u8fbc\u307f\u304c\u65e9\u304f\u306a\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java index e8c5ae4aea..3c0686c1a0 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java @@ -21,8 +21,6 @@ package org.sleuthkit.autopsy.corecomponents; import com.google.common.eventbus.Subscribe; import java.awt.Component; import java.awt.Cursor; -import java.awt.FontMetrics; -import java.awt.Graphics; import java.awt.dnd.DnDConstants; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; @@ -49,6 +47,7 @@ import javax.swing.JTable; import javax.swing.ListSelectionModel; import static javax.swing.SwingConstants.CENTER; import javax.swing.SwingUtilities; +import javax.swing.UIManager; import javax.swing.event.ChangeEvent; import javax.swing.event.ListSelectionEvent; import javax.swing.event.TableColumnModelEvent; @@ -106,6 +105,27 @@ public class DataResultViewerTable extends AbstractDataResultViewer { private static final long serialVersionUID = 1L; private static final Logger LOGGER = Logger.getLogger(DataResultViewerTable.class.getName()); + // How many rows to sample in order to determine column width. + private static final int SAMPLE_ROW_NUM = 100; + + // The padding to be added in addition to content size when considering column width. + private static final int COLUMN_PADDING = 15; + + // The minimum column width. + private static final int MIN_COLUMN_WIDTH = 30; + + // The maximum column width. + private static final int MAX_COLUMN_WIDTH = 300; + + // The minimum row height to use when calculating whether scroll bar will be used. + private static final int MIN_ROW_HEIGHT = 10; + + // The width of the scroll bar. + private static final int SCROLL_BAR_WIDTH = ((Integer) UIManager.get("ScrollBar.width")).intValue(); + + // Any additional padding to be used for the first column. + private static final int FIRST_COL_ADDITIONAL_WIDTH = 0; + private static final String NOTEPAD_ICON_PATH = "org/sleuthkit/autopsy/images/notepad16.png"; private static final String RED_CIRCLE_ICON_PATH = "org/sleuthkit/autopsy/images/red-circle-exclamation.png"; private static final String YELLOW_CIRCLE_ICON_PATH = "org/sleuthkit/autopsy/images/yellow-circle-yield.png"; @@ -152,7 +172,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { * OutlineView to the actions global context. * * @param explorerManager The explorer manager of the ancestor top - * component. + * component. */ public DataResultViewerTable(ExplorerManager explorerManager) { this(explorerManager, Bundle.DataResultViewerTable_title()); @@ -165,8 +185,8 @@ public class DataResultViewerTable extends AbstractDataResultViewer { * in the OutlineView to the actions global context. * * @param explorerManager The explorer manager of the ancestor top - * component. - * @param title The title. + * component. + * @param title The title. */ public DataResultViewerTable(ExplorerManager explorerManager, String title) { super(explorerManager); @@ -361,15 +381,10 @@ public class DataResultViewerTable extends AbstractDataResultViewer { * If the given node is not null and has children, set it as the * root context of the child OutlineView, otherwise make an * "empty"node the root context. - * - * IMPORTANT NOTE: This is the first of many times where a - * getChildren call on the current root node causes all of the - * children of the root node to be created and defeats lazy child - * node creation, if it is enabled. It also likely leads to many - * case database round trips. */ if (rootNode != null && rootNode.getChildren().getNodesCount() > 0) { this.getExplorerManager().setRootContext(this.rootNode); + outline.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); setupTable(); } else { Node emptyNode = new AbstractNode(Children.LEAF); @@ -422,13 +437,6 @@ public class DataResultViewerTable extends AbstractDataResultViewer { firstProp = props.remove(0); } - /* - * show the horizontal scroll panel and show all the content & header If - * there is only one column (which was removed from props above) Just - * let the table resize itself. - */ - outline.setAutoResizeMode((props.isEmpty()) ? JTable.AUTO_RESIZE_ALL_COLUMNS : JTable.AUTO_RESIZE_OFF); - assignColumns(props); // assign columns to match the properties if (firstProp != null) { ((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(firstProp.getDisplayName()); @@ -513,87 +521,59 @@ public class DataResultViewerTable extends AbstractDataResultViewer { /* * Sets the column widths for the child OutlineView of this tabular results - * viewer. + * viewer providing any additional width to last column. */ protected void setColumnWidths() { - if (rootNode.getChildren().getNodesCount() != 0) { - final Graphics graphics = outlineView.getGraphics(); + // based on https://stackoverflow.com/questions/17627431/auto-resizing-the-jtable-column-widths + final TableColumnModel columnModel = outline.getColumnModel(); - if (graphics != null) { - // Current width of the outlineView - double outlineViewWidth = outlineView.getSize().getWidth(); - // List of the column widths - List columnWidths = new ArrayList<>(); - final FontMetrics metrics = graphics.getFontMetrics(); + // the remaining table width that can be used in last row + double availableTableWidth = outlineView.getSize().getWidth(); - int margin = 4; - int padding = 8; + for (int columnIdx = 0; columnIdx < outline.getColumnCount(); columnIdx++) { + int columnPadding = (columnIdx == 0) ? FIRST_COL_ADDITIONAL_WIDTH + COLUMN_PADDING : COLUMN_PADDING; + TableColumn tableColumn = columnModel.getColumn(columnIdx); - int totalColumnWidth = 0; - int cntMaxSizeColumns = 0; + // The width of this column + int width = MIN_COLUMN_WIDTH; - // Calulate the width for each column keeping track of the number - // of columns that were set to columnwidthLimit. - for (int column = 0; column < outline.getModel().getColumnCount(); column++) { - int firstColumnPadding = (column == 0) ? 32 : 0; - int columnWidthLimit = (column == 0) ? 350 : 300; - int valuesWidth = 0; - - // find the maximum width needed to fit the values for the first 100 rows, at most - for (int row = 0; row < Math.min(100, outline.getRowCount()); row++) { - TableCellRenderer renderer = outline.getCellRenderer(row, column); - Component comp = outline.prepareRenderer(renderer, row, column); - valuesWidth = Math.max(comp.getPreferredSize().width, valuesWidth); - } - - int headerWidth = metrics.stringWidth(outline.getColumnName(column)); - valuesWidth += firstColumnPadding; // add extra padding for first column - - int columnWidth = Math.max(valuesWidth, headerWidth); - columnWidth += 2 * margin + padding; // add margin and regular padding - - columnWidth = Math.min(columnWidth, columnWidthLimit); - columnWidths.add(columnWidth); - - totalColumnWidth += columnWidth; - - if (columnWidth == columnWidthLimit) { - cntMaxSizeColumns++; - } - } - - // Figure out how much extra, if any can be given to the columns - // so that the table is as wide as outlineViewWidth. If cntMaxSizeColumns - // is greater than 0 divide the extra space between the columns - // that could use more space. Otherwise divide evenly amoung - // all columns. - int extraWidth = 0; - - if (totalColumnWidth < outlineViewWidth) { - if (cntMaxSizeColumns > 0) { - extraWidth = (int) ((outlineViewWidth - totalColumnWidth) / cntMaxSizeColumns); - } else { - extraWidth = (int) ((outlineViewWidth - totalColumnWidth) / columnWidths.size()); - } - } - - for (int column = 0; column < columnWidths.size(); column++) { - int columnWidth = columnWidths.get(column); - - if (cntMaxSizeColumns > 0) { - if (columnWidth >= ((column == 0) ? 350 : 300)) { - columnWidth += extraWidth; - } - } else { - columnWidth += extraWidth; - } - - outline.getColumnModel().getColumn(column).setPreferredWidth(columnWidth); - } + // get header cell width + // taken in part from https://stackoverflow.com/a/18381924 + TableCellRenderer headerRenderer = tableColumn.getHeaderRenderer(); + if (headerRenderer == null) { + headerRenderer = outline.getTableHeader().getDefaultRenderer(); + } + Object headerValue = tableColumn.getHeaderValue(); + Component headerComp = headerRenderer.getTableCellRendererComponent(outline, headerValue, false, false, 0, columnIdx); + width = Math.max(headerComp.getPreferredSize().width + columnPadding, width); + + // get the max of row widths from the first SAMPLE_ROW_NUM rows + Component comp = null; + int rowCount = outline.getRowCount(); + for (int row = 0; row < Math.min(rowCount, SAMPLE_ROW_NUM); row++) { + TableCellRenderer renderer = outline.getCellRenderer(row, columnIdx); + comp = outline.prepareRenderer(renderer, row, columnIdx); + width = Math.max(comp.getPreferredSize().width + columnPadding, width); + } + + // no higher than maximum column width + if (width > MAX_COLUMN_WIDTH) { + width = MAX_COLUMN_WIDTH; + } + + // if last column, calculate remaining width factoring in the possibility of a scroll bar. + if (columnIdx == outline.getColumnCount() - 1) { + int rowHeight = comp == null ? MIN_ROW_HEIGHT : comp.getPreferredSize().height; + if (headerComp.getPreferredSize().height + rowCount * rowHeight > outlineView.getSize().getHeight()) { + availableTableWidth -= SCROLL_BAR_WIDTH; + } + + columnModel.getColumn(columnIdx).setPreferredWidth(Math.max(width, (int) availableTableWidth)); + } else { + // otherwise set preferred width to width and decrement availableTableWidth accordingly + columnModel.getColumn(columnIdx).setPreferredWidth(width); + availableTableWidth -= width; } - } else { - // if there's no content just auto resize all columns - outline.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); } } @@ -749,7 +729,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { * order. * * @return a List> of the properties in the persisted - * order. + * order. */ private synchronized List> loadColumnOrder() { @@ -1266,18 +1246,20 @@ public class DataResultViewerTable extends AbstractDataResultViewer { /** * Returns the icon denoted by the Score's Significance. + * * @param significance The Score's Significance. + * * @return The icon (or null) related to that significance. */ private ImageIcon getIcon(Significance significance) { if (significance == null) { return null; } - + switch (significance) { case NOTABLE: return NOTABLE_ICON_SCORE; - case LIKELY_NOTABLE: + case LIKELY_NOTABLE: return INTERESTING_SCORE_ICON; case LIKELY_NONE: case NONE: @@ -1286,7 +1268,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { return null; } } - + @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentNode.java index dabb45ede2..0a43d47102 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentNode.java @@ -112,7 +112,7 @@ public abstract class AbstractContentNode extends ContentNode * @param lookup The Lookup object for the node. */ AbstractContentNode(T content, Lookup lookup) { - super(Children.create(new ContentChildren(content), false), lookup); + super(Children.create(new ContentChildren(content), true), lookup); this.content = content; //super.setName(ContentUtils.getSystemName(content)); super.setName("content_" + Long.toString(content.getId())); //NON-NLS diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Artifacts.java b/Core/src/org/sleuthkit/autopsy/datamodel/Artifacts.java index 796be557fd..cd0b03fd98 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Artifacts.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Artifacts.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2020 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -36,6 +36,7 @@ import org.openide.nodes.Node; import org.openide.nodes.Sheet; import org.openide.util.Lookup; import org.openide.util.NbBundle; +import org.openide.util.WeakListeners; import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; @@ -277,6 +278,8 @@ public class Artifacts { */ private final RefreshThrottler refreshThrottler = new RefreshThrottler(this); private final Category category; + + private final PropertyChangeListener weakPcl; /** * Main constructor. @@ -290,45 +293,50 @@ public class Artifacts { super(); this.filteringDSObjId = filteringDSObjId; this.category = category; - } - - private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> { - String eventType = evt.getPropertyName(); - if (eventType.equals(Case.Events.CURRENT_CASE.toString())) { - // case was closed. Remove listeners so that we don't get called with a stale case handle - if (evt.getNewValue() == null) { - removeNotify(); - } - } else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) - || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) { - /** - * This is a stop gap measure until a different way of handling - * the closing of cases is worked out. Currently, remote events - * may be received for a case that is already closed. - */ - try { - Case.getCurrentCaseThrows(); - refresh(false); - } catch (NoCurrentCaseException notUsed) { + + PropertyChangeListener pcl = (PropertyChangeEvent evt) -> { + String eventType = evt.getPropertyName(); + if (eventType.equals(Case.Events.CURRENT_CASE.toString())) { + // case was closed. Remove listeners so that we don't get called with a stale case handle + if (evt.getNewValue() == null) { + removeNotify(); + } + } else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) + || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) { /** - * Case is closed, do nothing. + * This is a stop gap measure until a different way of + * handling the closing of cases is worked out. Currently, + * remote events may be received for a case that is already + * closed. */ + try { + Case.getCurrentCaseThrows(); + refresh(false); + } catch (NoCurrentCaseException notUsed) { + /** + * Case is closed, do nothing. + */ + } } - } - }; + }; + weakPcl = WeakListeners.propertyChange(pcl, null); + } + @Override - protected void addNotify() { + protected void addNotify() { + super.addNotify(); refreshThrottler.registerForIngestModuleEvents(); - IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); - Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl); + Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); } @Override - protected void removeNotify() { + protected void finalize() throws Throwable { + super.finalize(); refreshThrottler.unregisterEventListener(); - IngestManager.getInstance().removeIngestJobEventListener(pcl); - Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); + IngestManager.getInstance().removeIngestJobEventListener(weakPcl); + Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); typeNodeMap.clear(); } @@ -624,17 +632,21 @@ public class Artifacts { } } }; + + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null); @Override protected void onAdd() { refreshThrottler.registerForIngestModuleEvents(); - IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl); } @Override protected void onRemove() { - refreshThrottler.unregisterEventListener(); - IngestManager.getInstance().removeIngestJobEventListener(pcl); + if(refreshThrottler != null) { + refreshThrottler.unregisterEventListener(); + } + IngestManager.getInstance().removeIngestJobEventListener(weakPcl); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyTreeChildFactory.java b/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyTreeChildFactory.java index 282ed83418..8321b8816a 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyTreeChildFactory.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyTreeChildFactory.java @@ -1,6 +1,5 @@ /* * Autopsy Forensic Browser - * * Copyright 2018-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * @@ -20,7 +19,6 @@ package org.sleuthkit.autopsy.datamodel; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.EnumSet; @@ -32,6 +30,7 @@ import java.util.stream.Collectors; import org.apache.commons.collections.CollectionUtils; import org.openide.nodes.ChildFactory; import org.openide.nodes.Node; +import org.openide.util.WeakListeners; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.CasePreferences; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; @@ -83,16 +82,18 @@ public final class AutopsyTreeChildFactory extends ChildFactory.Detachable extends ChildFactory.D isPageSizeChangeEvent = false; this.filter = filter; } - + @Override protected void addNotify() { onAdd(); } @Override - protected void removeNotify() { + protected void finalize() throws Throwable { + super.finalize(); onRemove(); } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/datamodel/Bundle_ja.properties index 761b704f2d..203bd41606 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Bundle_ja.properties @@ -1,4 +1,4 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Mon Jun 14 12:23:19 UTC 2021 AbstractAbstractFileNode.accessTimeColLbl=\u30a2\u30af\u30bb\u30b9\u65e5\u6642 AbstractAbstractFileNode.attrAddrColLbl=\u5c5e\u6027\u30a2\u30c9\u30ec\u30b9 AbstractAbstractFileNode.changeTimeColLbl=\u30a8\u30f3\u30c8\u30ea\u66f4\u65b0\u65e5\u6642 @@ -139,6 +139,7 @@ DataModelActionsFactory.fileInDir.text=\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30f DataModelActionsFactory.openExtViewer.text=\u5916\u90e8\u30d3\u30e5\u30fc\u30ef\u30fc\u3067\u958b\u304f Ctrl+E DataModelActionsFactory.srcFileInDir.text=\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fc\u5185\u306e\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb\u3092\u8868\u793a DataModelActionsFactory.viewNewWin.text=\u65b0\u3057\u3044\u30a6\u30a3\u30f3\u30c9\u30a6\u3067\u8868\u793a +DataSourcesHostsNode_name=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9 DataSourcesNode.createSheet.name.desc=\u8aac\u660e\u306a\u3057 DataSourcesNode.createSheet.name.displayName=\u540d\u524d DataSourcesNode.createSheet.name.name=\u540d\u524d @@ -226,6 +227,11 @@ GetSCOTask.occurrences.multipleProperties=\u3053\u306e\u7d50\u679c\u306b\u8907\u HashsetHits.createSheet.name.desc=\u8aac\u660e\u306a\u3057 HashsetHits.createSheet.name.displayName=\u540d\u524d HashsetHits.createSheet.name.name=\u540d\u524d +HostGroupingNode_unknownHostNode_title=\u672a\u77e5\u306e\u30db\u30b9\u30c8 +HostNode_actions_associateWithExisting=\u65e2\u5b58\u306e\u4eba\u3068\u95a2\u9023\u4ed8\u3051\u308b... +HostNode_actions_associateWithNew=\u65b0\u3057\u3044\u4eba\u3068\u95a2\u9023\u4ed8\u3051\u308b... +HostNode_actions_removeFromPerson=\u4eba\u304b\u3089\u524a\u9664\uff08{0}\uff09 +HostNode_createSheet_nameProperty=\u540d\u524d ImageNode.action.runIngestMods.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u5b9f\u884c ImageNode.createSheet.deviceId.desc=\u30a4\u30e1\u30fc\u30b8\u306e\u30c7\u30d0\u30a4\u30b9ID ImageNode.createSheet.deviceId.displayName=\u30c7\u30d0\u30a4\u30b9ID @@ -309,6 +315,23 @@ OpenReportAction.actionPerformed.MissingReportFileMessage=\u30ec\u30dd\u30fc\u30 OpenReportAction.actionPerformed.NoAssociatedEditorMessage=\u3053\u306e\u30bf\u30a4\u30d7\u306e\u30ec\u30dd\u30fc\u30c8\u306b\u95a2\u9023\u4ed8\u3051\u3089\u308c\u3066\u3044\u308b\u30a8\u30c7\u30a3\u30bf\u30fc\u304c\u306a\u3044\u304b\u3001\u95a2\u9023\u4ed8\u3051\u3089\u308c\u3066\u3044\u308b\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u304c\u8d77\u52d5\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 OpenReportAction.actionPerformed.NoOpenInEditorSupportMessage=\u3053\u306e\u30d7\u30e9\u30c3\u30c8\u30d5\u30a9\u30fc\u30e0(\u30aa\u30da\u30ec\u30fc\u30c6\u30a3\u30f3\u30b0\u30b7\u30b9\u30c6\u30e0)\u306f\u3053\u306e\u65b9\u6cd5\u3067\u30a8\u30c7\u30a3\u30bf\u30fc\u3067\u30d5\u30a1\u30a4\u30eb\u3092\u958b\u304f\u3053\u3068\u3092\u30b5\u30dd\u30fc\u30c8\u3057\u3066\u3044\u307e\u305b\u3093\u3002 OpenReportAction.actionPerformed.ReportFileOpenPermissionDeniedMessage=\u30ec\u30dd\u30fc\u30c8\u30d5\u30a1\u30a4\u30eb\u3092\u958b\u304f\u8a31\u53ef\u304c\u62d2\u5426\u3055\u308c\u307e\u3057\u305f\u3002 +OsAccount_listNode_name=OS\u30a2\u30ab\u30a6\u30f3\u30c8 +OsAccounts_accountNameProperty_desc=OS\u30a2\u30ab\u30a6\u30f3\u30c8\u540d +OsAccounts_accountNameProperty_displayName=\u540d\u524d +OsAccounts_accountNameProperty_name=\u540d\u524d +OsAccounts_accountRealmNameProperty_desc=OS\u30a2\u30ab\u30a6\u30f3\u30c8\u5206\u91ce\u540d +OsAccounts_accountRealmNameProperty_displayName=\u5206\u91ce\u540d +OsAccounts_accountRealmNameProperty_name=\u5206\u91ce\u540d +OsAccounts_createdTimeProperty_desc=OS\u30a2\u30ab\u30a6\u30f3\u30c8\u4f5c\u6210\u6642\u9593 +OsAccounts_createdTimeProperty_displayName=\u4f5c\u6210\u6642\u9593 +OsAccounts_createdTimeProperty_name=\u4f5c\u6210\u6642\u9593 +OsAccounts_loginNameProperty_desc=OS\u30a2\u30ab\u30a6\u30f3\u30c8\u30ed\u30b0\u30a4\u30f3\u540d +OsAccounts_loginNameProperty_displayName=\u30ed\u30b0\u30a4\u30f3\u540d +OsAccounts_loginNameProperty_name=\u30ed\u30b0\u30a4\u30f3\u540d +PersonGroupingNode_actions_delete=\u4eba\u306e\u524a\u9664 +PersonGroupingNode_actions_rename=\u540d\u524d\u3092\u5909\u66f4... +PersonGroupingNode_createSheet_nameProperty=\u540d\u524d +PersonNode_unknownPersonNode_title=\u672a\u77e5\u306e\u4eba\u7269 PoolNode.createSheet.name.desc=\u8aac\u660e\u306a\u3057 PoolNode.createSheet.name.displayName=\u540d\u524d PoolNode.createSheet.name.name=\u540d\u524d diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ContentChildren.java b/Core/src/org/sleuthkit/autopsy/datamodel/ContentChildren.java index 44885e1ef8..7b0987f623 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ContentChildren.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ContentChildren.java @@ -103,7 +103,21 @@ class ContentChildren extends AbstractContentChildren { @Override protected List makeKeys() { - return getDisplayChildren(parent); + List contentList = getDisplayChildren(parent); + + // Call the getUniquePath method to cache the value for future use + // in the EDT + contentList.forEach(content->{ + try { + content.getUniquePath(); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, String.format("Failed attempt to cache the " + + "unique path of the abstract file instance. Name: %s (objID=%d)", + content.getName(), content.getId()), ex); + } + }); + + return contentList; } @Override diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DataSourceFilesNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/DataSourceFilesNode.java index fd45f69bf0..b7e33860b9 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DataSourceFilesNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DataSourceFilesNode.java @@ -69,7 +69,7 @@ public class DataSourceFilesNode extends DisplayableItemNode { } public DataSourceFilesNode(long dsObjId) { - super(Children.create(new DataSourcesNodeChildren(dsObjId), false), Lookups.singleton(NAME)); + super(Children.create(new DataSourcesNodeChildren(dsObjId), true), Lookups.singleton(NAME)); displayName = (dsObjId > 0) ? NbBundle.getMessage(DataSourceFilesNode.class, "DataSourcesNode.group_by_datasource.name") : NAME; init(); } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DataSourcesNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/DataSourcesNode.java index c5fae53c03..e735eca3d9 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DataSourcesNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DataSourcesNode.java @@ -31,6 +31,7 @@ import org.openide.nodes.Node; import org.openide.nodes.Sheet; import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; +import org.openide.util.WeakListeners; import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; @@ -76,15 +77,18 @@ public class DataSourcesNode extends DisplayableItemNode { } } }; + + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null); @Override protected void addNotify() { - Case.addEventTypeSubscriber(UPDATE_EVTS, pcl); + Case.addEventTypeSubscriber(UPDATE_EVTS, weakPcl); } @Override - protected void removeNotify() { - Case.removeEventTypeSubscriber(UPDATE_EVTS, pcl); + protected void finalize() throws Throwable{ + Case.removeEventTypeSubscriber(UPDATE_EVTS, weakPcl); + super.finalize(); } @Override @@ -122,7 +126,7 @@ public class DataSourcesNode extends DisplayableItemNode { * Main constructor. */ DataSourcesNode() { - super(Children.create(new DataSourcesByTypeChildren(), false), Lookups.singleton(NAME)); + super(Children.create(new DataSourcesByTypeChildren(), true), Lookups.singleton(NAME)); setName(NAME); setDisplayName(NAME); this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/image.png"); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java b/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java index 0acd6a8bf3..9f8d1ee519 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2012-2020 Basis Technology Corp. + * Copyright 2012-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -37,6 +37,7 @@ import org.openide.nodes.Children; import org.openide.nodes.Node; import org.openide.nodes.Sheet; import org.openide.util.NbBundle; +import org.openide.util.WeakListeners; import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; @@ -313,21 +314,24 @@ public class EmailExtracted implements AutopsyVisitableItem { } } }; + + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null); @Override protected void addNotify() { - IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); - IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); - Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl); + Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); emailResults.update(); emailResults.addObserver(this); } @Override - protected void removeNotify() { - IngestManager.getInstance().removeIngestJobEventListener(pcl); - IngestManager.getInstance().removeIngestModuleEventListener(pcl); - Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); + protected void finalize() throws Throwable{ + super.finalize(); + IngestManager.getInstance().removeIngestJobEventListener(weakPcl); + IngestManager.getInstance().removeIngestModuleEventListener(weakPcl); + Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); emailResults.deleteObserver(this); } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java index e98b154ff0..970e546f98 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2020 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -39,6 +39,7 @@ import org.openide.nodes.Children; import org.openide.nodes.Node; import org.openide.nodes.Sheet; import org.openide.util.NbBundle; +import org.openide.util.WeakListeners; import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; @@ -278,21 +279,24 @@ public class HashsetHits implements AutopsyVisitableItem { } } }; + + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null); @Override protected void addNotify() { - IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); - IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); - Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl); + Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); hashsetResults.update(); hashsetResults.addObserver(this); } @Override - protected void removeNotify() { - IngestManager.getInstance().removeIngestJobEventListener(pcl); - IngestManager.getInstance().removeIngestModuleEventListener(pcl); - Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); + protected void finalize() throws Throwable { + super.finalize(); + IngestManager.getInstance().removeIngestJobEventListener(weakPcl); + IngestManager.getInstance().removeIngestModuleEventListener(weakPcl); + Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); hashsetResults.deleteObserver(this); } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/HostNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/HostNode.java index 08ce15cab6..b05bca24a1 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/HostNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/HostNode.java @@ -66,7 +66,7 @@ public class HostNode extends DisplayableItemNode { private final Host host; private final Function dataSourceToNode; - + /** * Main constructor. * @@ -77,7 +77,7 @@ public class HostNode extends DisplayableItemNode { this.host = host; this.dataSourceToNode = dataSourceToNode; } - + /** * Listener for handling DATA_SOURCE_ADDED / HOST_DELETED events. * A host may have been deleted as part of a merge, which means its data sources could @@ -93,15 +93,19 @@ public class HostNode extends DisplayableItemNode { } } }; - + + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(dataSourceAddedPcl, null); + @Override protected void addNotify() { - Case.addEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED, Case.Events.HOSTS_DELETED), dataSourceAddedPcl); + super.addNotify(); + Case.addEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED, Case.Events.HOSTS_DELETED), weakPcl); } @Override - protected void removeNotify() { - Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED, Case.Events.HOSTS_DELETED), dataSourceAddedPcl); + protected void finalize() throws Throwable { + super.finalize(); + Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED, Case.Events.HOSTS_DELETED), weakPcl); } @Override @@ -212,7 +216,7 @@ public class HostNode extends DisplayableItemNode { * @param hosts The HostDataSources key. */ HostNode(HostDataSources hosts) { - this(Children.create(new HostGroupingChildren(HOST_DATA_SOURCES, hosts.getHost()), false), hosts.getHost()); + this(Children.create(new HostGroupingChildren(HOST_DATA_SOURCES, hosts.getHost()), true), hosts.getHost()); } /** diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ImageNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/ImageNode.java index ea0e2bb347..5df888052b 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ImageNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ImageNode.java @@ -20,8 +20,6 @@ package org.sleuthkit.autopsy.datamodel; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; -import java.sql.ResultSet; -import java.sql.SQLException; import java.util.ArrayList; import java.util.Collections; import java.util.EnumSet; @@ -35,7 +33,6 @@ import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.DeleteDataSourceAction; -import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.datasourcesummary.ui.ViewSummaryInformationAction; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance; import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable; @@ -48,7 +45,6 @@ import org.sleuthkit.autopsy.ingest.ModuleContentEvent; import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.RunIngestModulesAction; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Image; -import org.sleuthkit.datamodel.SleuthkitCase.CaseDbQuery; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.VirtualDirectory; import org.sleuthkit.autopsy.datamodel.BaseChildFactory.NoSuchEventBusException; @@ -171,17 +167,10 @@ public class ImageNode extends AbstractContentNode { Bundle.ImageNode_createSheet_timezone_desc(), this.content.getTimeZone())); - try (CaseDbQuery query = Case.getCurrentCaseThrows().getSleuthkitCase().executeQuery("SELECT device_id FROM data_source_info WHERE obj_id = " + this.content.getId());) { - ResultSet deviceIdSet = query.getResultSet(); - if (deviceIdSet.next()) { - sheetSet.put(new NodeProperty<>(Bundle.ImageNode_createSheet_deviceId_name(), + sheetSet.put(new NodeProperty<>(Bundle.ImageNode_createSheet_deviceId_name(), Bundle.ImageNode_createSheet_deviceId_displayName(), Bundle.ImageNode_createSheet_deviceId_desc(), - deviceIdSet.getString("device_id"))); - } - } catch (SQLException | TskCoreException | NoCurrentCaseException ex) { - logger.log(Level.SEVERE, "Failed to get device id for the following image: " + this.content.getId(), ex); - } + content.getDeviceId())); return sheet; } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/InterestingHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/InterestingHits.java index 57f2524ff9..f636264082 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/InterestingHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/InterestingHits.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2020 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -39,6 +39,7 @@ import org.openide.nodes.Children; import org.openide.nodes.Node; import org.openide.nodes.Sheet; import org.openide.util.NbBundle; +import org.openide.util.WeakListeners; import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; @@ -271,21 +272,24 @@ public class InterestingHits implements AutopsyVisitableItem { } } }; - + + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null); + @Override protected void addNotify() { - IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); - IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); - Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl); + Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); interestingResults.update(); interestingResults.addObserver(this); } @Override - protected void removeNotify() { - IngestManager.getInstance().removeIngestJobEventListener(pcl); - IngestManager.getInstance().removeIngestModuleEventListener(pcl); - Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); + protected void finalize() throws Throwable { + super.finalize(); + IngestManager.getInstance().removeIngestJobEventListener(weakPcl); + IngestManager.getInstance().removeIngestModuleEventListener(weakPcl); + Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); interestingResults.deleteObserver(this); } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java index 7a9683b89f..4406944fa3 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java @@ -42,6 +42,7 @@ import org.openide.nodes.Node; import org.openide.nodes.Sheet; import org.openide.util.Lookup; import org.openide.util.NbBundle; +import org.openide.util.WeakListeners; import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; @@ -437,7 +438,8 @@ public class KeywordHits implements AutopsyVisitableItem { } @Override - protected void removeNotify() { + protected void finalize() throws Throwable { + super.finalize(); keywordResults.deleteObserver(this); } @@ -504,22 +506,24 @@ public class KeywordHits implements AutopsyVisitableItem { } }; + + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null); @Override protected void addNotify() { - IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); - IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); - Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl); + Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); keywordResults.update(); super.addNotify(); } @Override - protected void removeNotify() { - IngestManager.getInstance().removeIngestJobEventListener(pcl); - IngestManager.getInstance().removeIngestModuleEventListener(pcl); - Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); - super.removeNotify(); + protected void finalize() throws Throwable{ + IngestManager.getInstance().removeIngestJobEventListener(weakPcl); + IngestManager.getInstance().removeIngestModuleEventListener(weakPcl); + Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); + super.finalize(); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/OsAccounts.java b/Core/src/org/sleuthkit/autopsy/datamodel/OsAccounts.java index 65875ef0ed..75a6eb971b 100755 --- a/Core/src/org/sleuthkit/autopsy/datamodel/OsAccounts.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/OsAccounts.java @@ -137,19 +137,22 @@ public final class OsAccounts implements AutopsyVisitableItem { } } }; + + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(listener, null); + @Override + protected void finalize() throws Throwable { + super.finalize(); + Case.removeEventTypeSubscriber(Collections.singleton(Case.Events.OS_ACCOUNTS_ADDED), weakPcl); + Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); + } + @Override protected void addNotify() { Case.addEventTypeSubscriber(EnumSet.of(Case.Events.OS_ACCOUNTS_ADDED, Case.Events.OS_ACCOUNTS_DELETED), listener); Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), listener); } - @Override - protected void removeNotify() { - Case.removeEventTypeSubscriber(Collections.singleton(Case.Events.OS_ACCOUNTS_ADDED), listener); - Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), listener); - } - @Override protected boolean createKeys(List list) { if (skCase != null) { diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/PersonNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/PersonNode.java index 99db59211b..a6cd30b115 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/PersonNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/PersonNode.java @@ -92,6 +92,7 @@ public class PersonNode extends DisplayableItemNode { */ PersonChildren(Person person) { this.person = person; + } /** @@ -111,17 +112,20 @@ public class PersonNode extends DisplayableItemNode { } } }; + + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(hostAddedDeletedPcl, null); @Override protected void addNotify() { - Case.addEventTypeSubscriber(HOST_EVENTS_OF_INTEREST, hostAddedDeletedPcl); + Case.addEventTypeSubscriber(HOST_EVENTS_OF_INTEREST, weakPcl); } - + @Override - protected void removeNotify() { - Case.removeEventTypeSubscriber(HOST_EVENTS_OF_INTEREST, hostAddedDeletedPcl); + protected void finalize() throws Throwable { + super.finalize(); + Case.removeEventTypeSubscriber(HOST_EVENTS_OF_INTEREST, weakPcl); } - + @Override protected HostNode createNodeForKey(HostGrouping key) { return key == null ? null : new HostNode(key); @@ -203,7 +207,7 @@ public class PersonNode extends DisplayableItemNode { * @param displayName The display name for the person. */ private PersonNode(Person person, String displayName) { - super(Children.create(new PersonChildren(person), false), + super(Children.create(new PersonChildren(person), true), person == null ? Lookups.fixed(displayName) : Lookups.fixed(person, displayName)); super.setName(displayName); super.setDisplayName(displayName); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java index 6fa6487b5e..8154d5a884 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2019 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -33,6 +33,7 @@ import org.openide.nodes.Children; import org.openide.nodes.Node; import org.openide.nodes.Sheet; import org.openide.util.NbBundle; +import org.openide.util.WeakListeners; import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; @@ -213,6 +214,8 @@ public class Tags implements AutopsyVisitableItem { } } }; + + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null); /** * Constructor @@ -221,21 +224,21 @@ public class Tags implements AutopsyVisitableItem { */ TagNameNodeFactory(long objId) { this.filteringDSObjId = objId; - } - + @Override protected void addNotify() { - IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); - Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl); + Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, weakPcl); tagResults.update(); tagResults.addObserver(this); } @Override - protected void removeNotify() { - IngestManager.getInstance().removeIngestJobEventListener(pcl); - Case.removeEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, pcl); + protected void finalize() throws Throwable { + super.finalize(); + IngestManager.getInstance().removeIngestJobEventListener(weakPcl); + Case.removeEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, weakPcl); tagResults.deleteObserver(this); } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/accounts/Accounts.java b/Core/src/org/sleuthkit/autopsy/datamodel/accounts/Accounts.java index 901ab4aeb8..bf7ee1caba 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/accounts/Accounts.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/accounts/Accounts.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2019 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -57,6 +57,7 @@ import org.openide.nodes.NodeOp; import org.openide.nodes.Sheet; import org.openide.util.NbBundle; import org.openide.util.Utilities; +import org.openide.util.WeakListeners; import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; @@ -218,8 +219,8 @@ final public class Accounts implements AutopsyVisitableItem { abstract void handleDataAdded(ModuleDataEvent event); @Override - protected void removeNotify() { - super.removeNotify(); + protected void finalize() throws Throwable { + super.finalize(); reviewStatusBus.unregister(ObservingChildren.this); } @@ -415,6 +416,8 @@ final public class Accounts implements AutopsyVisitableItem { } } }; + + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null); @Subscribe @Override @@ -473,18 +476,18 @@ final public class Accounts implements AutopsyVisitableItem { } @Override - protected void removeNotify() { - IngestManager.getInstance().removeIngestJobEventListener(pcl); - IngestManager.getInstance().removeIngestModuleEventListener(pcl); - Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); - super.removeNotify(); + protected void finalize() throws Throwable { + IngestManager.getInstance().removeIngestJobEventListener(weakPcl); + IngestManager.getInstance().removeIngestModuleEventListener(weakPcl); + Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); + super.finalize(); } @Override protected void addNotify() { - IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); - IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); - Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl); + Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); super.addNotify(); refresh(true); } @@ -550,21 +553,22 @@ final public class Accounts implements AutopsyVisitableItem { } } }; - + + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null); + @Override protected void addNotify() { - IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); - IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); - Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); - super.addNotify(); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl); + Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); } @Override - protected void removeNotify() { - IngestManager.getInstance().removeIngestJobEventListener(pcl); - IngestManager.getInstance().removeIngestModuleEventListener(pcl); - Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); - super.removeNotify(); + protected void finalize() throws Throwable { + super.finalize(); + IngestManager.getInstance().removeIngestJobEventListener(weakPcl); + IngestManager.getInstance().removeIngestModuleEventListener(weakPcl); + Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); } @Override @@ -727,6 +731,9 @@ final public class Accounts implements AutopsyVisitableItem { } } }; + + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null); + @Subscribe @Override @@ -739,20 +746,21 @@ final public class Accounts implements AutopsyVisitableItem { void handleDataAdded(ModuleDataEvent event) { refresh(true); } - + @Override protected void addNotify() { - IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); - IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); - Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl); + Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); super.addNotify(); } @Override - protected void removeNotify() { - IngestManager.getInstance().removeIngestJobEventListener(pcl); - IngestManager.getInstance().removeIngestModuleEventListener(pcl); - Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); + protected void finalize() throws Throwable { + super.finalize(); + IngestManager.getInstance().removeIngestJobEventListener(weakPcl); + IngestManager.getInstance().removeIngestModuleEventListener(weakPcl); + Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); super.removeNotify(); } @@ -881,21 +889,23 @@ final public class Accounts implements AutopsyVisitableItem { } } }; + + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null); @Override protected void addNotify() { - IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); - IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); - Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl); + Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); super.addNotify(); } @Override - protected void removeNotify() { - IngestManager.getInstance().removeIngestJobEventListener(pcl); - IngestManager.getInstance().removeIngestModuleEventListener(pcl); - Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); - super.removeNotify(); + protected void finalize() throws Throwable { + super.finalize(); + IngestManager.getInstance().removeIngestJobEventListener(weakPcl); + IngestManager.getInstance().removeIngestModuleEventListener(weakPcl); + Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); } @Subscribe @@ -1095,21 +1105,23 @@ final public class Accounts implements AutopsyVisitableItem { } } }; + + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null); @Override protected void addNotify() { - IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); - IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); - Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl); + Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); super.addNotify(); } @Override - protected void removeNotify() { - IngestManager.getInstance().removeIngestJobEventListener(pcl); - IngestManager.getInstance().removeIngestModuleEventListener(pcl); - Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); - super.removeNotify(); + protected void finalize() throws Throwable{ + super.finalize(); + IngestManager.getInstance().removeIngestJobEventListener(weakPcl); + IngestManager.getInstance().removeIngestModuleEventListener(weakPcl); + Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); } @Subscribe diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/hosts/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/datamodel/hosts/Bundle_ja.properties new file mode 100644 index 0000000000..2798b41330 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datamodel/hosts/Bundle_ja.properties @@ -0,0 +1,41 @@ +#Mon Jun 14 12:23:19 UTC 2021 +AddEditHostDialog.cancelButton.text=\u30ad\u30e3\u30f3\u30bb\u30eb +AddEditHostDialog.inputTextField.text=jTextField1 +AddEditHostDialog.nameLabel.text=\u540d\u524d\uff1a +AddEditHostDialog.okButton.text=OK +AddEditHostDialog_addHost_title=\u30db\u30b9\u30c8\u3092\u8ffd\u52a0 +AddEditHostDialog_editHost_title=\u30db\u30b9\u30c8\u306e\u7de8\u96c6 +AssociateNewPersonAction_menuTitle=\u65b0\u3057\u3044\u4eba... +AssociateNewPersonAction_onError_description=\u30db\u30b9\u30c8{0}\u3092\u65b0\u3057\u3044\u4eba{1}\u306b\u95a2\u9023\u4ed8\u3051\u308b\u3068\u304d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +AssociateNewPersonAction_onError_title=\u65b0\u3057\u3044\u4eba\u306e\u95a2\u9023\u4ed8\u3051\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +AssociatePersonAction_onError_description=\u30db\u30b9\u30c8{0}\u3068\u500b\u4eba{1}\u306e\u95a2\u9023\u4ed8\u3051\u3067\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +AssociatePersonAction_onError_title=\u30db\u30b9\u30c8\u3068\u500b\u4eba\u306e\u95a2\u9023\u4ed8\u3051\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +AssociatePersonAction_unknownPerson=\u5931\u540d\u6c0f +AssociatePersonsMenuAction_menuTitle=\u4eba\u3068\u95a2\u9023\u4ed8\u3051\u308b +CTL_OpenHosts=\u30db\u30b9\u30c8\u306e\u7ba1\u7406 +HostNameValidator_getValidationMessage_onDuplicate=\u5225\u306e\u30db\u30b9\u30c8\u306f\u3059\u3067\u306b\u540c\u3058\u540d\u524d\u3092\u6301\u3063\u3066\u3044\u307e\u3059\u3002 \u5225\u306e\u540d\u524d\u306b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +HostNameValidator_getValidationMessage_onEmpty=\u30db\u30b9\u30c8\u540d\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +HostNameValidator_getValidationMessage_sameAsOriginal=\u3053\u306e\u30db\u30b9\u30c8\u306e\u65b0\u3057\u3044\u540d\u524d\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +ManageHostsDialog.closeButton.text=\u9589\u3058\u308b +ManageHostsDialog.deleteButton.text=\u524a\u9664 +ManageHostsDialog.editButton.text=\u7de8\u96c6 +ManageHostsDialog.hostDescriptionTextArea.text=\u30db\u30b9\u30c8\u306f\u3001\u8907\u6570\u306e\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u6301\u3064\u53ef\u80fd\u6027\u306e\u3042\u308b\u500b\u3005\u306e\u30c7\u30d0\u30a4\u30b9\u3092\u8868\u3057\u307e\u3059\u3002 +ManageHostsDialog.hostDetailsLabel.text=\u30db\u30b9\u30c8\u306e\u8a73\u7d30 +ManageHostsDialog.hostListLabel.text=\u30db\u30b9\u30c8 +ManageHostsDialog.hostNameLabel.text=\u30db\u30b9\u30c8\u540d\uff1a +ManageHostsDialog.newButton.text=\u65b0 +ManageHostsDialog_title_text=\u30db\u30b9\u30c8\u306e\u7ba1\u7406 +MergeHostAction.confirmText={0}\u3092{1}\u306b\u30de\u30fc\u30b8\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b\uff1f\n\u3053\u308c\u306b\u306fOS\u30a2\u30ab\u30a6\u30f3\u30c8\u306e\u30de\u30fc\u30b8\u304c\u542b\u307e\u308c\u308b\u5834\u5408\u304c\u3042\u308a\u3001\u5143\u306b\u623b\u3059\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093\u3002 +MergeHostAction.confirmTitle=\u78ba\u8a8d +MergeHostAction.errorText=\u30db\u30b9\u30c8\u306e\u30de\u30fc\u30b8\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002\n\u6570\u5206\u5f8c\u306b\u3082\u3046\u4e00\u5ea6\u8a66\u3059\u304b\u3001\u30ed\u30b0\u3067\u8a73\u7d30\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +MergeHostAction.errorTitle=\u30db\u30b9\u30c8\u306e\u30de\u30fc\u30b8\u30a8\u30e9\u30fc +MergeHostAction.progressIndicatorName=\u30db\u30b9\u30c8\u306e\u30de\u30fc\u30b8 +MergeHostAction.progressText={0}\u3092{1}\u306b\u30de\u30fc\u30b8\u3057\u3066\u3044\u307e\u3059... +MergeHostAction_onError_description=\u30db\u30b9\u30c8{0}\u3092\u30db\u30b9\u30c8{1}\u306b\u30de\u30fc\u30b8\u3059\u308b\u3068\u304d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +MergeHostAction_onError_title=\u30db\u30b9\u30c8\u306e\u30de\u30fc\u30b8\u30a8\u30e9\u30fc +MergeHostMenuAction_menuTitle=\u4ed6\u306e\u30db\u30b9\u30c8\u306b\u30de\u30fc\u30b8\u3059\u308b +OpenHostsAction_displayName=\u30db\u30b9\u30c8 +RemoveParentPersonAction_menuTitle=\u4eba\u304b\u3089\u524a\u9664\uff08{0}\uff09 +RemoveParentPersonAction_onError_description=\u30db\u30b9\u30c8\u304b\u3089\u4eba\u3092\u524a\u9664\u3059\u308b\u3068\u304d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a{0}\u3002 +RemoveParentPersonAction_onError_title=\u500b\u4eba\u304b\u3089\u30db\u30b9\u30c8\u3092\u524a\u9664\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +RemoveParentPersonAction_unknownPerson=\u5931\u540d\u6c0f diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/persons/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/datamodel/persons/Bundle_ja.properties new file mode 100644 index 0000000000..5e808b7db7 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datamodel/persons/Bundle_ja.properties @@ -0,0 +1,19 @@ +#Mon Jun 14 12:23:19 UTC 2021 +AddEditPersonDialog.cancelButton.text=\u30ad\u30e3\u30f3\u30bb\u30eb +AddEditPersonDialog.cancelButton.text_1=\u30ad\u30e3\u30f3\u30bb\u30eb +AddEditPersonDialog.inputTextField.text_1=jTextField1 +AddEditPersonDialog.nameLabel.text=\u540d\u524d\uff1a +AddEditPersonDialog.nameLabel.text_1=\u540d\u524d\uff1a +AddEditPersonDialog.okButton.text=OK +AddEditPersonDialog.okButton.text_1=OK +AddEditPersonDialog_addPerson_title=\u4eba\u3092\u8ffd\u52a0 +AddEditPersonDialog_editPerson_title=\u4eba\u306e\u7de8\u96c6 +DeletePersonAction_menuTitle=\u4eba\u306e\u524a\u9664 +DeletePersonAction_onError_description=\u4eba\u306e\u524a\u9664\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a{0}\u3002 +DeletePersonAction_onError_title=\u500b\u4eba\u304b\u3089\u30db\u30b9\u30c8\u3092\u524a\u9664\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +EditPersonAction_menuTitle=\u4eba\u306e\u7de8\u96c6\u3002\u3002\u3002 +EditPersonAction_onError_description=\u4eba\u306e\u7de8\u96c6\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a{0}\u3002 +EditPersonAction_onError_title=\u4eba\u306e\u7de8\u96c6\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +PersonNameValidator_getValidationMessage_onDuplicate=\u540c\u3058\u540d\u524d\u304c\u65e2\u306b\u5b58\u5728\u3057\u3066\u3044\u307e\u3059\u3002 \u5225\u306e\u540d\u524d\u3092\u9078\u3093\u3067\u304f\u3060\u3055\u3044\u3002 +PersonNameValidator_getValidationMessage_onEmpty=\u540d\u524d\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +PersonNameValidator_getValidationMessage_sameAsOriginal=\u3053\u306e\u4eba\u306e\u65b0\u3057\u3044\u540d\u524d\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/Bundle_ja.properties index 5873c044cc..a8185f73ff 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/Bundle_ja.properties @@ -1,4 +1,3 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Mon Jun 14 12:23:19 UTC 2021 DataSourceUserActivitySummary_getRecentAccounts_calllogMessage=\u901a\u8a71\u8a18\u9332 DataSourceUserActivitySummary_getRecentAccounts_emailMessage=\u30e1\u30fc\u30eb\u30e1\u30c3\u30bb\u30fc\u30b8 -IngestModuleCheckUtil_recentActivityModuleName=\u6700\u8fd1\u306e\u6d3b\u52d5 diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle_ja.properties index 2b4d2c7dc2..053ceb7450 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle_ja.properties @@ -1,11 +1,13 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Mon Jun 14 12:23:19 UTC 2021 AnalysisPanel.hashsetHitsLabel.text=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u30d2\u30c3\u30c8 AnalysisPanel.interestingItemLabel.text=\u8208\u5473\u6df1\u3044\u30a2\u30a4\u30c6\u30e0\u306e\u30d2\u30c3\u30c8 AnalysisPanel.keywordHitsLabel.text=\u30ad\u30fc\u30ef\u30fc\u30c9\u30d2\u30c3\u30c8 AnalysisPanel_countColumn_title=\u30ab\u30a6\u30f3\u30c8 +AnalysisPanel_hashsetHits_tabName=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u30fb\u30d2\u30c3\u30c8 +AnalysisPanel_interestingItemHits_tabName=\u8208\u5473\u6df1\u3044\u30a2\u30a4\u30c6\u30e0\u306e\u30d2\u30c3\u30c8 AnalysisPanel_keyColumn_title=\u540d\u524d +AnalysisPanel_keywordHits_tabName=\u30ad\u30fc\u30ef\u30fc\u30c9\u30fb\u30d2\u30c3\u30c8 AnalysisPanel_keywordSearchModuleName=\u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22 -BaseDataSourceSummaryPanel_defaultNotIngestMessage={0}\u53d6\u8fbc\u307f\u30e2\u30b8\u30e5\u30fc\u30eb\u306f\u3053\u306e\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3067\u306f\u5b9f\u884c\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002 BaseDataSourceSummaryPanel_goToArtifact=\u30bd\u30fc\u30b9\u7d50\u679c\u306e\u8868\u793a BaseDataSourceSummaryPanel_goToFile=\u30d5\u30a9\u30eb\u30c0\u30fc\u5185\u306e\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb\u3092\u8868\u793a CTL_DataSourceSummaryAction=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306e\u6982\u8981 @@ -30,7 +32,21 @@ ContainerPanel.units.kilobytes=\ kB ContainerPanel.units.megabytes=\ MB ContainerPanel.units.petabytes=\ PB ContainerPanel.units.terabytes=\ TB +ContainerPanel_export_acquisitionDetails=\u8aad\u8fbc\u306e\u8a73\u7d30\uff1a +ContainerPanel_export_deviceId=\u30c7\u30d0\u30a4\u30b9ID\uff1a +ContainerPanel_export_displayName=\u8868\u793a\u540d\uff1a +ContainerPanel_export_filePaths=\u30d5\u30a1\u30a4\u30eb\u30d1\u30b9\uff1a +ContainerPanel_export_imageType=\u753b\u50cf\u30bf\u30a4\u30d7\uff1a +ContainerPanel_export_md5=MD5\: +ContainerPanel_export_originalName=\u540d\u524d\uff1a +ContainerPanel_export_sectorSize=\u30bb\u30af\u30bf\u30fc\u30b5\u30a4\u30ba\uff1a +ContainerPanel_export_sha1=SHA1\: +ContainerPanel_export_sha256=SHA256\: +ContainerPanel_export_size=\u30b5\u30a4\u30ba\uff1a +ContainerPanel_export_timeZone=\u30bf\u30a4\u30e0\u30be\u30fc\u30f3\uff1a +ContainerPanel_export_unallocatedSize=\u672a\u5272\u308a\u5f53\u3066\u9818\u57df\uff1a ContainerPanel_setFieldsForNonImageDataSource_na=\u8a72\u5f53\u306a\u3057 +ContainerPanel_tabName=\u30b3\u30f3\u30c6\u30ca DataSourceSummaryCountsPanel.FilesByCategoryTableModel.all.row=\u3059\u3079\u3066 DataSourceSummaryCountsPanel.FilesByCategoryTableModel.allocated.row=\u5272\u308a\u5f53\u3066\u6e08\u307f DataSourceSummaryCountsPanel.FilesByCategoryTableModel.count.header=\u30ab\u30a6\u30f3\u30c8 @@ -63,6 +79,7 @@ DataSourceSummaryNode.viewDataSourceAction.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u DataSourceSummaryTabbedPane.noDataSourceLabel.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002 DataSourceSummaryTabbedPane_analysisTab_title=\u5206\u6790 DataSourceSummaryTabbedPane_detailsTab_title=\u30b3\u30f3\u30c6\u30ca +DataSourceSummaryTabbedPane_exportTab_title=\u30a8\u30af\u30b9\u30dd\u30fc\u30c8 DataSourceSummaryTabbedPane_geolocationTab_title=\u30b8\u30aa\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3 DataSourceSummaryTabbedPane_ingestHistoryTab_title=\u53d6\u8fbc\u5c65\u6b74 DataSourceSummaryTabbedPane_pastCasesTab_title=\u904e\u53bb\u306e\u30b1\u30fc\u30b9 @@ -70,21 +87,46 @@ DataSourceSummaryTabbedPane_recentFileTab_title=\u6700\u8fd1\u4f7f\u7528\u3057\u DataSourceSummaryTabbedPane_timelineTab_title=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3 DataSourceSummaryTabbedPane_typesTab_title=\u30bf\u30a4\u30d7 DataSourceSummaryTabbedPane_userActivityTab_title=\u30e6\u30fc\u30b6\u30fc\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3 +ExcelExportAction_exportToXLSX_beginExport=\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u3092\u958b\u59cb\u3057\u3066\u3044\u307e\u3059... +ExcelExportAction_exportToXLSX_gatheringTabData={0}\u30bf\u30d6\u306e\u30c7\u30fc\u30bf\u3092\u53d6\u5f97\u3057\u3066\u3044\u307e\u3059... +ExcelExportAction_exportToXLSX_writingToFile=\u30d5\u30a1\u30a4\u30eb\u3078\u306e\u66f8\u51fa\u3057\u4e2d... +ExcelExportAction_getXLSXPath_directory=DataSourceSummary +ExcelExportAction_moduleName=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306e\u6982\u8981 +ExcelExportAction_runXLSXExport_errorMessage=\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +ExcelExportAction_runXLSXExport_errorTitle=\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +ExcelExportAction_runXLSXExport_progressCancelActionTitle=\u30ad\u30e3\u30f3\u30bb\u30eb... +ExcelExportAction_runXLSXExport_progressCancelTitle=\u30ad\u30e3\u30f3\u30bb\u30eb +ExcelExportAction_runXLSXExport_progressTitle={0}\u3092XLSX\u306b\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u3057\u3066\u3044\u307e\u3059 +ExcelExportDialog.okButton.text=OK +ExcelExportDialog.titleLabel.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306e\u6982\u8981\u306f\u6b21\u306e\u5834\u6240\u306b\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u3055\u308c\u307e\u3057\u305f\uff1a +ExcelExportDialog_title=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306e\u6982\u8981\u304c\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u3055\u308c\u307e\u3057\u305f +ExportPanel.xlsxExportButton.text=\u8981\u7d04\u30c7\u30fc\u30bf\u306e\u30a8\u30af\u30b9\u30dd\u30fc\u30c8 +ExportPanel.xlsxExportMessage.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u30b5\u30de\u30ea\u30fc\u304b\u3089Excel\u30d5\u30a1\u30a4\u30eb\u306b\u30c7\u30fc\u30bf\u3092\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u3057\u307e\u3059\u3002 GeolocationPanel.commonViewInGeolocationBtn.text=\u5730\u56f3\u3067\u898b\u308b -GeolocationPanel.mostCommonLabel.text=\u30b8\u30aa\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3\u304b\u3089\u306e\u6700\u3082\u4e00\u822c\u7684\u306a\u90fd\u5e02 -GeolocationPanel.mostRecentLabel.text=\u30b8\u30aa\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u304b\u3089\u306e\u6700\u8fd1\u306e\u90fd\u5e02 +GeolocationPanel.mostCommonLabel.text=\u30b8\u30aa\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u7d50\u679c\u304b\u3089\u6700\u3082\u4e00\u822c\u7684\u306a\u90fd\u5e02 +GeolocationPanel.mostRecentLabel.text=\u30b8\u30aa\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u7d50\u679c\u3067\u306e\u6700\u8fd1\u306e\u90fd\u5e02 GeolocationPanel.recentViewInGeolocationBtn.text=\u5730\u56f3\u3067\u898b\u308b GeolocationPanel.withinDistanceLabel.text=\u90fd\u5e02\u304b\u3089150km\u4ee5\u4e0a\u96e2\u308c\u305f\u5834\u6240\u306f\u3001\u300c\u4e0d\u660e\u300d\u3068\u3057\u3066\u8868\u793a\u3055\u308c\u307e\u3059 GeolocationPanel.withinDistanceLabel1.text=\u90fd\u5e02\u304b\u3089150km\u4ee5\u4e0a\u96e2\u308c\u305f\u5834\u6240\u306f\u3001\u300c\u4e0d\u660e\u300d\u3068\u3057\u3066\u8868\u793a\u3055\u308c\u307e\u3059 GeolocationPanel_cityColumn_title=\u6700\u3082\u8fd1\u3044\u90fd\u5e02 GeolocationPanel_countColumn_title=\u30ab\u30a6\u30f3\u30c8 +GeolocationPanel_mostCommon_tabName=\u6700\u3082\u4e00\u822c\u7684\u306a\u90fd\u5e02 +GeolocationPanel_mostRecent_tabName=\u6700\u8fd1\u4f7f\u7528\u3055\u308c\u305f\u90fd\u5e02 GeolocationPanel_onNoCrIngest_message=GPX\u30d1\u30fc\u30b5\u30fc\u304c\u5b9f\u884c\u3055\u308c\u306a\u304b\u3063\u305f\u305f\u3081\u3001\u7d50\u679c\u306f\u8868\u793a\u3055\u308c\u307e\u305b\u3093\u3002 GeolocationPanel_unknownRow_title=\u4e0d\u660e +IngestJobExcelExport_endTimeColumn=\u7d42\u4e86\u6642\u9593 +IngestJobExcelExport_ingestStatusTimeColumn=\u53d6\u8fbc\u307f\u72b6\u6cc1 +IngestJobExcelExport_moduleNameTimeColumn=\u30e2\u30b8\u30e5\u30fc\u30eb\u540d +IngestJobExcelExport_sheetName=\u53d6\u8fbc\u307f\u6b74\u53f2 +IngestJobExcelExport_startTimeColumn=\u30b9\u30bf\u30fc\u30c8\u6642\u9593 +IngestJobExcelExport_versionColumn=\u30e2\u30b8\u30e5\u30fc\u30eb\u30d0\u30fc\u30b8\u30e7\u30f3 PastCasesPanel.notableFileLabel.text=\u300c\u6ce8\u76ee\u300d\u3068\u30bf\u30b0\u4ed8\u3051\u3055\u308c\u305f\u4e00\u822c\u7684\u306a\u30b1\u30fc\u30b9 PastCasesPanel.sameIdLabel.text=\u540c\u3058\u30c7\u30d0\u30a4\u30b9ID\u3092\u6301\u3064\u904e\u53bb\u306e\u30b1\u30fc\u30b9 PastCasesPanel_caseColumn_title=\u30b1\u30fc\u30b9 PastCasesPanel_countColumn_title=\u30ab\u30a6\u30f3\u30c8 +PastCasesPanel_notableFileTable_tabName=\u4e00\u822c\u7684\u306b\u6ce8\u76ee\u3059\u3079\u304d\u4e8b\u4f8b PastCasesPanel_onNoCrIngest_message=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u5b9f\u884c\u3055\u308c\u306a\u304b\u3063\u305f\u305f\u3081\u3001\u7d50\u679c\u306f\u8868\u793a\u3055\u308c\u307e\u305b\u3093\u3002 +PastCasesPanel_sameIdsTable_tabName=\u540c\u3058\u30c7\u30d0\u30a4\u30b9\u3067\u306e\u904e\u53bb\u306e\u30b1\u30fc\u30b9 RecentFilePanel_col_header_domain=\u30c9\u30e1\u30a4\u30f3 RecentFilePanel_col_header_path=\u30d1\u30b9 RecentFilePanel_col_header_sender=\u9001\u4fe1\u8005 @@ -96,21 +138,31 @@ RecentFilesPanel.openDocsLabel.text=\u6700\u8fd1\u958b\u3044\u305f\u30c9\u30ad\u RecentFilesPanel.rightClickForMoreOptions1.text=\u305d\u306e\u4ed6\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u306b\u3064\u3044\u3066\u306f\u3001\u884c\u3092\u53f3\u30af\u30ea\u30c3\u30af\u3057\u3066\u304f\u3060\u3055\u3044 RecentFilesPanel.rightClickForMoreOptions2.text=\u305d\u306e\u4ed6\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u306b\u3064\u3044\u3066\u306f\u3001\u884c\u3092\u53f3\u30af\u30ea\u30c3\u30af\u3057\u3066\u304f\u3060\u3055\u3044 RecentFilesPanel.rightClickForMoreOptions3.text=\u305d\u306e\u4ed6\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u306b\u3064\u3044\u3066\u306f\u3001\u884c\u3092\u53f3\u30af\u30ea\u30c3\u30af\u3057\u3066\u304f\u3060\u3055\u3044 +RecentFilesPanel_attachmentsTable_tabName=\u6700\u8fd1\u306e\u6dfb\u4ed8\u30d5\u30a1\u30a4\u30eb RecentFilesPanel_col_head_date=\u65e5\u4ed8 +RecentFilesPanel_docsTable_tabName=\u6700\u8fd1\u958b\u3044\u305f\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8 +RecentFilesPanel_downloadsTable_tabName=\u6700\u8fd1\u306e\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9 SizeRepresentationUtil_units_bytes=\u30d0\u30a4\u30c8 -SizeRepresentationUtil_units_gigabytes=\ GB -SizeRepresentationUtil_units_kilobytes=\ kB -SizeRepresentationUtil_units_megabytes=\ MB -SizeRepresentationUtil_units_petabytes=\ PB -SizeRepresentationUtil_units_terabytes=\ TB +SizeRepresentationUtil_units_gigabytes=GB +SizeRepresentationUtil_units_kilobytes=KB +SizeRepresentationUtil_units_megabytes=MB +SizeRepresentationUtil_units_petabytes=PB +SizeRepresentationUtil_units_terabytes=TB TimelinePanel.activityRangeLabel.text=\u6d3b\u52d5\u7bc4\u56f2 TimelinePanel.viewInTimelineBtn.text=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u3067\u8868\u793a TimelinePanel_earliestLabel_title=\u6700\u53e4 +TimelinePanel_getExports_activityRange=\u6d3b\u52d5\u7bc4\u56f2 +TimelinePanel_getExports_chartName=\u904e\u53bb30\u65e5\u9593 +TimelinePanel_getExports_dateColumnHeader=\u65e5\u4ed8 +TimelinePanel_getExports_earliest=\u6700\u53e4\uff1a +TimelinePanel_getExports_latest=\u6700\u8fd1\uff1a +TimelinePanel_getExports_sheetName=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3 TimelinePanel_latestLabel_title=\u6700\u65b0 TimlinePanel_last30DaysChart_artifactEvts_title=\u7d50\u679c\u30a4\u30d9\u30f3\u30c8 TimlinePanel_last30DaysChart_fileEvts_title=\u30d5\u30a1\u30a4\u30eb\u30a4\u30d9\u30f3\u30c8 TimlinePanel_last30DaysChart_title=\u904e\u53bb30\u65e5\u9593 TypesPanel_artifactsTypesPieChart_title=\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u30bf\u30a4\u30d7 +TypesPanel_excelTabName=\u30bf\u30a4\u30d7 TypesPanel_fileMimeTypesChart_audio_title=\u30aa\u30fc\u30c7\u30a3\u30aa TypesPanel_fileMimeTypesChart_documents_title=\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8 TypesPanel_fileMimeTypesChart_executables_title=\u5b9f\u884c\u53ef\u80fd\u30d5\u30a1\u30a4\u30eb @@ -119,6 +171,7 @@ TypesPanel_fileMimeTypesChart_notAnalyzed_title=\u5206\u6790\u3055\u308c\u3066\u TypesPanel_fileMimeTypesChart_other_title=\u305d\u306e\u4ed6 TypesPanel_fileMimeTypesChart_title=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7 TypesPanel_fileMimeTypesChart_unknown_title=\u4e0d\u660e +TypesPanel_fileMimeTypesChart_valueLabel=\u30ab\u30a6\u30f3\u30c8 TypesPanel_fileMimeTypesChart_videos_title=\u30d3\u30c7\u30aa TypesPanel_filesByCategoryTable_allocatedRow_title=\u5272\u308a\u5f53\u3066\u3089\u308c\u305f\u30d5\u30a1\u30a4\u30eb TypesPanel_filesByCategoryTable_directoryRow_title=\u30d5\u30a9\u30eb\u30c0 @@ -139,18 +192,23 @@ UserActivityPanel.topDevicesAttachedLabel.text=\u6700\u8fd1\u63a5\u7d9a\u3055\u3 UserActivityPanel.topWebSearchLabel.text=\u6700\u8fd1\u306eWeb\u691c\u7d22 UserActivityPanel_TopAccountTableModel_accountType_header=\u30a2\u30ab\u30f3\u30c8\u30bf\u30a4\u30d7 UserActivityPanel_TopAccountTableModel_lastAccess_header=\u6700\u7d42\u30a2\u30af\u30bb\u30b9\u65e5 +UserActivityPanel_TopAccountTableModel_tabName=\u6700\u8fd1\u4f7f\u7528\u3055\u308c\u305f\u30a2\u30ab\u30a6\u30f3\u30c8\u30bf\u30a4\u30d7 UserActivityPanel_TopDeviceAttachedTableModel_dateAccessed_header=\u6700\u7d42\u30a2\u30af\u30bb\u30b9\u65e5 UserActivityPanel_TopDeviceAttachedTableModel_deviceId_header=\u30c7\u30d0\u30a4\u30b9ID UserActivityPanel_TopDeviceAttachedTableModel_makeModel_header=\u30e1\u30fc\u30ab\u30fc\u3068\u30e2\u30c7\u30eb +UserActivityPanel_TopDeviceAttachedTableModel_tabName=\u6700\u8fd1\u63a5\u7d9a\u3055\u308c\u305f\u30c7\u30d0\u30a4\u30b9 UserActivityPanel_TopDomainsTableModel_count_header=\u53c2\u89b3 UserActivityPanel_TopDomainsTableModel_domain_header=\u30c9\u30e1\u30a4\u30f3 UserActivityPanel_TopDomainsTableModel_lastAccess_header=\u6700\u7d42\u30a2\u30af\u30bb\u30b9\u65e5 +UserActivityPanel_TopDomainsTableModel_tabName=\u6700\u8fd1\u306e\u30c9\u30e1\u30a4\u30f3 UserActivityPanel_TopProgramsTableModel_count_header=\u5b9f\u884c\u6642\u9593 UserActivityPanel_TopProgramsTableModel_folder_header=\u30d5\u30a9\u30eb\u30c0 UserActivityPanel_TopProgramsTableModel_lastrun_header=\u524d\u56de\u5b9f\u884c UserActivityPanel_TopProgramsTableModel_name_header=\u30d7\u30ed\u30b0\u30e9\u30e0 +UserActivityPanel_TopProgramsTableModel_tabName=\u6700\u8fd1\u306e\u30d7\u30ed\u30b0\u30e9\u30e0 UserActivityPanel_TopWebSearchTableModel_dateAccessed_header=\u30a2\u30af\u30bb\u30b9\u65e5 UserActivityPanel_TopWebSearchTableModel_searchString_header=\u691c\u7d22\u6587\u5b57\u5217 +UserActivityPanel_TopWebSearchTableModel_tabName=\u6700\u8fd1\u306eWeb\u691c\u7d22 UserActivityPanel_TopWebSearchTableModel_translatedResult_header=\u7ffb\u8a33\u6e08\u307f UserActivityPanel_noDataExists=\u901a\u4fe1\u30c7\u30fc\u30bf\u304c\u3042\u308a\u307e\u305b\u3093 UserActivityPanel_tab_title=\u30e6\u30fc\u30b6\u30fc\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3 diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryNode.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryNode.java index a4c48e7adf..4aa3cf1be3 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryNode.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryNode.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 Basis Technology Corp. + * Copyright 2019-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -30,7 +30,6 @@ import org.openide.nodes.Children; import org.openide.nodes.Node; import org.openide.nodes.Sheet; import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.datasourcesummary.ui.Bundle; import org.sleuthkit.autopsy.datamodel.NodeProperty; import org.sleuthkit.autopsy.directorytree.ViewContextAction; import org.sleuthkit.datamodel.DataSource; @@ -59,7 +58,7 @@ final class DataSourceSummaryNode extends AbstractNode { * DataSources which are this nodes children */ DataSourceSummaryNode(List dataSourceList) { - super(Children.create(new DataSourceSummaryChildren(dataSourceList), false)); + super(Children.create(new DataSourceSummaryChildren(dataSourceList), true)); } /** diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/Bundle_ja.properties index 25a7ef2e76..1807aad546 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/Bundle_ja.properties @@ -1,6 +1,7 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Mon Jun 14 12:23:19 UTC 2021 AbstractLoadableComponent_errorMessage_defaultText=\u7d50\u679c\u306e\u8aad\u8fbc\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 AbstractLoadableComponent_loadingMessage_defaultText=\u7d50\u679c\u3092\u8aad\u8fbc\u4e2d... AbstractLoadableComponent_noDataExists_defaultText=\u30c7\u30fc\u30bf\u306f\u5b58\u5728\u3057\u307e\u305b\u3093\u3002 +ExcelExport_writeExcel_noSheetName=\u30b7\u30fc\u30c8{0} IngestRunningLabel_defaultMessage=\u53d6\u8fbc\u307f\u5b9f\u884c\u4e2d\u3067\u3059\u3002 PieChartPanel_noDataLabel=\u30c7\u30fc\u30bf\u7121\u3057 diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/directorytree/Bundle_ja.properties index d9ae2561f4..81e23b1ad9 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/directorytree/Bundle_ja.properties @@ -1,4 +1,4 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Mon Jun 14 12:23:19 UTC 2021 AddExternalViewerRuleDialog.cancelButton.title=\u53d6\u308a\u6d88\u3057 AddExternalViewerRuleDialog.saveButton.title=\u4fdd\u5b58 AddExternalViewerRuleDialog.title=\u5916\u90e8\u30d3\u30e5\u30fc\u30ef\u30fc\u30eb\u30fc\u30eb diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ViewContextAction.java b/Core/src/org/sleuthkit/autopsy/directorytree/ViewContextAction.java index c8f5848243..323b340c7f 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ViewContextAction.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ViewContextAction.java @@ -31,6 +31,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import org.sleuthkit.autopsy.coreutils.Logger; import javax.swing.AbstractAction; +import org.apache.commons.lang3.StringUtils; import org.openide.nodes.AbstractNode; import org.openide.explorer.ExplorerManager; import org.openide.explorer.view.TreeView; @@ -84,7 +85,7 @@ public class ViewContextAction extends AbstractAction { * parent of the content, selecting the parent in the tree view, then * selecting the content in the results view. * - * @param displayName The display name for the action. + * @param displayName The display name for the action. * @param artifactNode The artifact node for the artifact. */ public ViewContextAction(String displayName, BlackboardArtifactNode artifactNode) { @@ -106,9 +107,9 @@ public class ViewContextAction extends AbstractAction { * parent of the content, selecting the parent in the tree view, then * selecting the content in the results view. * - * @param displayName The display name for the action. + * @param displayName The display name for the action. * @param fileSystemContentNode The file system content node for the - * content. + * content. */ public ViewContextAction(String displayName, AbstractFsContentNode fileSystemContentNode) { super(displayName); @@ -121,9 +122,9 @@ public class ViewContextAction extends AbstractAction { * content, selecting the parent in the tree view, then selecting the * content in the results view. * - * @param displayName The display name for the action. + * @param displayName The display name for the action. * @param abstractAbstractFileNode The AbstractAbstractFileNode node for the - * content. + * content. */ public ViewContextAction(String displayName, AbstractAbstractFileNode abstractAbstractFileNode) { super(displayName); @@ -137,7 +138,7 @@ public class ViewContextAction extends AbstractAction { * content in the results view. * * @param displayName The display name for the action. - * @param content The content. + * @param content The content. */ public ViewContextAction(String displayName, Content content) { super(displayName); @@ -149,7 +150,7 @@ public class ViewContextAction extends AbstractAction { * branch of the tree view to the level of the parent of the content, * selecting the parent in the tree view, then selecting the content in the * results view. - * + * * NOTE: This code will likely need updating in the event that the structure * of the nodes is changed (i.e. adding parent levels). Places to look when * changing node structure include: @@ -168,176 +169,224 @@ public class ViewContextAction extends AbstractAction { public void actionPerformed(ActionEvent event) { EventQueue.invokeLater(() -> { - /* - * Get the parent content for the content to be selected in the - * results view. If the parent content is null, then the specified - * content is a data source, and the parent tree view node is the - * "Data Sources" node. Otherwise, the tree view needs to be - * searched to find the parent treeview node. - */ - Content parentContent = null; - try { - parentContent = content.getParent(); - } catch (TskCoreException ex) { - MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_cannotFindDirectory()); - logger.log(Level.SEVERE, String.format("Could not get parent of Content object: %s", content), ex); //NON-NLS - return; - } - - if ((parentContent != null) - && (parentContent instanceof UnsupportedContent)) { + Content parentContent = getParentContent(this.content); + + if ((parentContent != null) && (parentContent instanceof UnsupportedContent)) { MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_unsupportedParent()); logger.log(Level.WARNING, String.format("Could not navigate to unsupported content with id: %d", parentContent.getId())); //NON-NLS return; } - /* - * Get the "Data Sources" node from the tree view. - */ + // Get the "Data Sources" node from the tree view. DirectoryTreeTopComponent treeViewTopComponent = DirectoryTreeTopComponent.findInstance(); ExplorerManager treeViewExplorerMgr = treeViewTopComponent.getExplorerManager(); + Node parentTreeViewNode = null; - if (Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)) { // 'Group by Data Source' view - - SleuthkitCase skCase; - String dsname; - try { - // get the objid/name of the datasource of the selected content. - skCase = Case.getCurrentCaseThrows().getSleuthkitCase(); - long contentDSObjid = content.getDataSource().getId(); - DataSource datasource = skCase.getDataSource(contentDSObjid); - dsname = datasource.getName(); - Children rootChildren = treeViewExplorerMgr.getRootContext().getChildren(); - - if (null != parentContent) { - // the tree view needs to be searched to find the parent treeview node. - /* NOTE: we can't do a lookup by data source name here, becase if there - are multiple data sources with the same name, then "getChildren().findChild(dsname)" - simply returns the first one that it finds. Instead we have to loop over all - data sources with that name, and make sure we find the correct one. - */ - List dataSourceLevelNodes = Stream.of(rootChildren.getNodes()) - .flatMap(rootNode -> getDataSourceLevelNodes(rootNode).stream()) - .collect(Collectors.toList()); - - for (Node treeNode : dataSourceLevelNodes) { - // in the root, look for a data source node with the name of interest - if (!(treeNode.getName().equals(dsname))) { - continue; - } - - // for this data source, get the "Data Sources" child node - Node datasourceGroupingNode = treeNode.getChildren().findChild(DataSourceFilesNode.getNameIdentifier()); - - // check whether this is the data source we are looking for - parentTreeViewNode = findParentNodeInTree(parentContent, datasourceGroupingNode); - if (parentTreeViewNode != null) { - // found the data source node - break; - } - } - } else { - /* If the parent content is null, then the specified - * content is a data source, and the parent tree view node is the - * "Data Sources" node. */ - Node datasourceGroupingNode = rootChildren.findChild(dsname); - if (!Objects.isNull(datasourceGroupingNode)) { - Children dsChildren = datasourceGroupingNode.getChildren(); - parentTreeViewNode = dsChildren.findChild(DataSourceFilesNode.getNameIdentifier()); - } - } - - if (parentTreeViewNode == null) { - MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_cannotFindNode()); - logger.log(Level.SEVERE, "Failed to locate data source node in tree."); //NON-NLS - return; - } - } catch (NoCurrentCaseException | TskDataException | TskCoreException ex) { - MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_cannotFindNode()); - logger.log(Level.SEVERE, "Failed to locate data source node in tree.", ex); //NON-NLS - return; - } - } else { // Classic view - // Start the search at the DataSourcesNode - Children rootChildren = treeViewExplorerMgr.getRootContext().getChildren(); - Node rootDsNode = rootChildren == null ? null : rootChildren.findChild(DataSourcesNode.getNameIdentifier()); - if (rootDsNode != null) { - for (Node dataSourceLevelNode : getDataSourceLevelNodes(rootDsNode)) { - DataSource dataSource = dataSourceLevelNode.getLookup().lookup(DataSource.class); - if (dataSource != null) { - // the tree view needs to be searched to find the parent treeview node. - Node potentialParentTreeViewNode = findParentNodeInTree(parentContent, dataSourceLevelNode); - if (potentialParentTreeViewNode != null) { - parentTreeViewNode = potentialParentTreeViewNode; - break; - } - } - } + if (parentContent != null) { + if (Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)) { + parentTreeViewNode = getParentNodeGroupedByPersonHost(treeViewExplorerMgr, parentContent); + } else { + parentTreeViewNode = getParentNodeGroupedByDataSource(treeViewExplorerMgr, parentContent); } } - /* - * Set the child selection info of the parent tree node, then select - * the parent node in the tree view. The results view will retrieve - * this selection info and use it to complete this action when the - * tree view top component responds to the selection of the parent - * node by pushing it into the results view top component. - */ - DisplayableItemNode undecoratedParentNode = (DisplayableItemNode) ((DirectoryTreeFilterNode) parentTreeViewNode).getOriginal(); - undecoratedParentNode.setChildNodeSelectionInfo(new ContentNodeSelectionInfo(content)); - if (content instanceof BlackboardArtifact) { - BlackboardArtifact artifact = ((BlackboardArtifact) content); - long associatedId = artifact.getObjectID(); - try { - Content associatedFileContent = artifact.getSleuthkitCase().getContentById(associatedId); - undecoratedParentNode.setChildNodeSelectionInfo(new ContentNodeSelectionInfo(associatedFileContent)); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Could not find associated content from artifact with id %d", artifact.getId()); - } + // if no node is found, report error and do nothing + if (parentTreeViewNode == null) { + MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_cannotFindNode()); + logger.log(Level.SEVERE, "Failed to locate data source node in tree."); //NON-NLS + return; } - TreeView treeView = treeViewTopComponent.getTree(); - treeView.expandNode(parentTreeViewNode); - if (treeViewTopComponent.getSelectedNode().equals(parentTreeViewNode)) { - //In the case where our tree view already has the destination directory selected - //due to an optimization in the ExplorerManager.setExploredContextAndSelection method - //the property change we listen for to call DirectoryTreeTopComponent.respondSelection - //will not be sent so we call it manually ourselves after making - //the directory listing the active tab. - treeViewTopComponent.setDirectoryListingActive(); - treeViewTopComponent.respondSelection(treeViewExplorerMgr.getSelectedNodes(), new Node[]{parentTreeViewNode}); - } else { - try { - treeViewExplorerMgr.setExploredContextAndSelection(parentTreeViewNode, new Node[]{parentTreeViewNode}); - } catch (PropertyVetoException ex) { - MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_cannotSelectDirectory()); - logger.log(Level.SEVERE, "Failed to select the parent node in the tree view", ex); //NON-NLS - } - } + setNodeSelection(this.content, parentTreeViewNode, treeViewTopComponent, treeViewExplorerMgr); }); } + /** + * Get the parent content for the content to be selected in the results + * view. If the parent content is null, then the specified content is a data + * source, and the parent tree view node is the "Data Sources" node. + * Otherwise, the tree view needs to be searched to find the parent treeview + * node. + * + * @param content The content whose parent will be returned. If this item is + * a datasource, it will be returned. + * + * @return The content if content is a data source or the parent of this + * content. + */ + private Content getParentContent(Content content) { + + try { + return (content instanceof DataSource) + ? content + : content.getParent(); + } catch (TskCoreException ex) { + MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_cannotFindDirectory()); + logger.log(Level.SEVERE, String.format("Could not get parent of Content object: %s", content), ex); //NON-NLS + return null; + } + } + + /** + * Returns the node in the tree related to the parentContent or null if + * can't be found. This method should be used when view is grouped by data + * source. + * + * @param treeViewExplorerMgr The explorer manager. + * @param parentContent The content whose equivalent node will be + * returned if found. + * + * @return The node if found or null. + */ + private Node getParentNodeGroupedByDataSource(ExplorerManager treeViewExplorerMgr, Content parentContent) { + // Classic view + // Start the search at the DataSourcesNode + Children rootChildren = treeViewExplorerMgr.getRootContext().getChildren(); + Node rootDsNode = rootChildren == null ? null : rootChildren.findChild(DataSourcesNode.getNameIdentifier()); + if (rootDsNode != null) { + for (Node dataSourceLevelNode : getDataSourceLevelNodes(rootDsNode)) { + DataSource dataSource = dataSourceLevelNode.getLookup().lookup(DataSource.class); + if (dataSource != null) { + // the tree view needs to be searched to find the parent treeview node. + Node potentialParentTreeViewNode = findParentNodeInTree(parentContent, dataSourceLevelNode); + if (potentialParentTreeViewNode != null) { + return potentialParentTreeViewNode; + } + } + } + } + + return null; + } + + /** + * Returns the node in the tree related to the parentContent or null if + * can't be found. This method should be used when view is grouped by + * hosts/persons. + * + * @param treeViewExplorerMgr The explorer manager. + * @param parentContent The content whose equivalent node will be + * returned if found. + * + * @return The node if found or null. + */ + private Node getParentNodeGroupedByPersonHost(ExplorerManager treeViewExplorerMgr, Content parentContent) { + // 'Group by Data Source' view + + SleuthkitCase skCase; + String dsname; + try { + // get the objid/name of the datasource of the selected content. + skCase = Case.getCurrentCaseThrows().getSleuthkitCase(); + long contentDSObjid = parentContent.getDataSource().getId(); + DataSource datasource = skCase.getDataSource(contentDSObjid); + dsname = datasource.getName(); + Children rootChildren = treeViewExplorerMgr.getRootContext().getChildren(); + + // the tree view needs to be searched to find the parent treeview node. + /* NOTE: we can't do a lookup by data source name here, becase if there + are multiple data sources with the same name, then "getChildren().findChild(dsname)" + simply returns the first one that it finds. Instead we have to loop over all + data sources with that name, and make sure we find the correct one. + */ + List dataSourceLevelNodes = Stream.of(rootChildren.getNodes(true)) + .flatMap(rootNode -> getDataSourceLevelNodes(rootNode).stream()) + .collect(Collectors.toList()); + + for (Node treeNode : dataSourceLevelNodes) { + // in the root, look for a data source node with the name of interest + if (!(treeNode.getName().equals(dsname))) { + continue; + } + + // for this data source, get the "Data Sources" child node + Node datasourceGroupingNode = treeNode.getChildren().findChild(DataSourceFilesNode.getNameIdentifier()); + + // check whether this is the data source we are looking for + Node parentTreeViewNode = findParentNodeInTree(parentContent, datasourceGroupingNode); + if (parentTreeViewNode != null) { + // found the data source node + return parentTreeViewNode; + } + } + } catch (NoCurrentCaseException | TskDataException | TskCoreException ex) { + MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_cannotFindNode()); + logger.log(Level.SEVERE, "Failed to locate data source node in tree.", ex); //NON-NLS + } + + return null; + } + + /** + * Set the node selection in the tree. + * @param content The content to select. + * @param parentTreeViewNode The node that is the parent of the content. + * @param treeViewTopComponent The DirectoryTreeTopComponent. + * @param treeViewExplorerMgr The ExplorerManager. + */ + private void setNodeSelection(Content content, Node parentTreeViewNode, DirectoryTreeTopComponent treeViewTopComponent, ExplorerManager treeViewExplorerMgr) { + /* + * Set the child selection info of the parent tree node, then select + * the parent node in the tree view. The results view will retrieve + * this selection info and use it to complete this action when the + * tree view top component responds to the selection of the parent + * node by pushing it into the results view top component. + */ + DisplayableItemNode undecoratedParentNode = (DisplayableItemNode) ((DirectoryTreeFilterNode) parentTreeViewNode).getOriginal(); + undecoratedParentNode.setChildNodeSelectionInfo(new ContentNodeSelectionInfo(content)); + if (content instanceof BlackboardArtifact) { + BlackboardArtifact artifact = ((BlackboardArtifact) content); + long associatedId = artifact.getObjectID(); + try { + Content associatedFileContent = artifact.getSleuthkitCase().getContentById(associatedId); + undecoratedParentNode.setChildNodeSelectionInfo(new ContentNodeSelectionInfo(associatedFileContent)); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Could not find associated content from artifact with id %d", artifact.getId()); + } + } + + TreeView treeView = treeViewTopComponent.getTree(); + treeView.expandNode(parentTreeViewNode); + if (treeViewTopComponent.getSelectedNode().equals(parentTreeViewNode)) { + //In the case where our tree view already has the destination directory selected + //due to an optimization in the ExplorerManager.setExploredContextAndSelection method + //the property change we listen for to call DirectoryTreeTopComponent.respondSelection + //will not be sent so we call it manually ourselves after making + //the directory listing the active tab. + treeViewTopComponent.setDirectoryListingActive(); + treeViewTopComponent.respondSelection(treeViewExplorerMgr.getSelectedNodes(), new Node[]{parentTreeViewNode}); + } else { + try { + treeViewExplorerMgr.setExploredContextAndSelection(parentTreeViewNode, new Node[]{parentTreeViewNode}); + } catch (PropertyVetoException ex) { + MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_cannotSelectDirectory()); + logger.log(Level.SEVERE, "Failed to select the parent node in the tree view", ex); //NON-NLS + } + } + } + /** * If the node has lookup of host or person, returns children. If not, just * returns itself. * * @param node The node. + * * @return The child nodes that are at the data source level. */ private List getDataSourceLevelNodes(Node node) { if (node == null) { return Collections.emptyList(); - } else if (node.getLookup().lookup(Host.class) != null || - node.getLookup().lookup(Person.class) != null || - DataSourcesNode.getNameIdentifier().equals(node.getLookup().lookup(String.class)) || - PersonNode.getUnknownPersonId().equals(node.getLookup().lookup(String.class))) { + } else if (node.getLookup().lookup(Host.class) != null + || node.getLookup().lookup(Person.class) != null + || DataSourcesNode.getNameIdentifier().equals(node.getLookup().lookup(String.class)) + || PersonNode.getUnknownPersonId().equals(node.getLookup().lookup(String.class))) { Children children = node.getChildren(); - Node[] childNodes = children == null ? null : children.getNodes(); + Node[] childNodes = children == null ? null : children.getNodes(true); if (childNodes == null) { return Collections.emptyList(); } - return Stream.of(node.getChildren().getNodes()) + return Stream.of(node.getChildren().getNodes(true)) .flatMap(parent -> getDataSourceLevelNodes(parent).stream()) .collect(Collectors.toList()); } else { @@ -350,7 +399,8 @@ public class ViewContextAction extends AbstractAction { * of the specified content. * * @param parentContent parent content for the content to be searched for - * @param node Node tree to search + * @param node Node tree to search + * * @return Node object of the matching parent, NULL if not found */ private Node findParentNodeInTree(Content parentContent, Node node) { @@ -377,6 +427,11 @@ public class ViewContextAction extends AbstractAction { Node dummyRootNode = new DirectoryTreeFilterNode(new AbstractNode(new RootContentChildren(contentBranch)), true); Children ancestorChildren = dummyRootNode.getChildren(); + // if content is the data source provided, return that. + if (ancestorChildren.getNodesCount() == 1 && StringUtils.equals(ancestorChildren.getNodeAt(0).getName(), node.getName())) { + return node; + } + /* * Search the tree for the parent node. Note that this algorithm * simply discards "extra" ancestor nodes not shown in the tree, @@ -387,8 +442,9 @@ public class ViewContextAction extends AbstractAction { Node parentTreeViewNode = null; for (int i = 0; i < ancestorChildren.getNodesCount(); i++) { Node ancestorNode = ancestorChildren.getNodeAt(i); - for (int j = 0; j < treeNodeChildren.getNodesCount(); j++) { - Node treeNode = treeNodeChildren.getNodeAt(j); + Node[] treeNodeChilds = treeNodeChildren.getNodes(true); + for (int j = 0; j < treeNodeChilds.length; j++) { + Node treeNode = treeNodeChilds[j]; if (ancestorNode.getName().equals(treeNode.getName())) { parentTreeViewNode = treeNode; treeNodeChildren = treeNode.getChildren(); diff --git a/Core/src/org/sleuthkit/autopsy/discovery/search/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/discovery/search/Bundle_ja.properties index 13b93f98f2..1a00933afe 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/search/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/discovery/search/Bundle_ja.properties @@ -1,4 +1,4 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Mon Jun 14 12:23:19 UTC 2021 DiscoveryAttributes.ActivityDateGroupKey.getDisplayNameTemplate={0}{1}\u3001{2}\u306e\u9031 DiscoveryAttributes.GroupingAttributeType.datasource.displayName=\u30c7\u30fc\u30bf\u5143 DiscoveryAttributes.GroupingAttributeType.fileType.displayName=\u30d5\u30a1\u30a4\u30eb\u306e\u7a2e\u985e @@ -48,6 +48,7 @@ FileSorter.SortingMethod.fullPath.displayName=\u30d5\u30eb\u30d1\u30b9 FileSorter.SortingMethod.keywordlist.displayName=\u30ad\u30fc\u30ef\u30fc\u30c9\u30ea\u30b9\u30c8\u540d FileSorter.SortingMethod.pageViews.displayName=\u30da\u30fc\u30b8\u30d3\u30e5\u30fc ResultDomain_getDefaultCategory=\u672a\u5206\u985e +ResultDomain_noAccountTypes=\u4e0d\u660e ResultFile.score.interestingResult.description=1\u3064\u4ee5\u4e0a\u306e\u30d5\u30a1\u30a4\u30eb\u306b\u8208\u5473\u6df1\u3044\u7d50\u679c\u304c\u95a2\u9023\u4ed8\u3051\u3089\u308c\u3066\u3044\u307e\u3059\u3002 ResultFile.score.notableFile.description=1\u3064\u4ee5\u4e0a\u306e\u30d5\u30a1\u30a4\u30eb\u304c\u6ce8\u76ee\u3059\u3079\u304d\u3082\u306e\u3068\u3057\u3066\u8a8d\u8b58\u3055\u308c\u307e\u3057\u305f\u3002 ResultFile.score.notableTaggedFile.description=1\u3064\u4ee5\u4e0a\u306e\u30d5\u30a1\u30a4\u30eb\u304c\u6ce8\u76ee\u3059\u3079\u304d\u30bf\u30b0\u4ed8\u3051\u3055\u308c\u3066\u3044\u307e\u3059\u3002 diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle_ja.properties index f8235ab6e3..54e640b4b9 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle_ja.properties @@ -1,4 +1,5 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Mon Jun 14 12:23:19 UTC 2021 +ArtifactMenuMouseAdapter.noFile.text=\u30d5\u30a1\u30a4\u30eb\u304c\u5b58\u5728\u3057\u307e\u305b\u3093\u3002 ArtifactMenuMouseAdapter_ExternalViewer_label=\u5916\u90e8\u30d3\u30e5\u30fc\u30a2\u3067\u958b\u304f ArtifactMenuMouseAdapter_label=\u30d5\u30a1\u30a4\u30eb\u306e\u62bd\u51fa ArtifactTypeFilterPanel.artifactTypeCheckbox.text=\u7d50\u679c\u30bf\u30a4\u30d7\uff1a @@ -23,7 +24,7 @@ DateFilterPanel.dateRange.text=\u65e5\u4ed8\u7bc4\u56f2\uff08{0}\uff09\uff1a DateFilterPanel.daysLabel.text=\u6d3b\u52d5\u65e5 DateFilterPanel.endCheckBox.text=\u7d42\u4e86\uff1a DateFilterPanel.invalidRange.text=\u7bc4\u56f2\u307e\u305f\u306f\u6700\u5f8c\u3092\u9078\u629e\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 -DateFilterPanel.mostRecentRadioButton.text=\u6700\u5f8c\u306e\u307f\uff1a +DateFilterPanel.mostRecentRadioButton.text=\u6700\u7d42\u306e\u307f\uff1a DateFilterPanel.startAfterEnd.text=\u4e21\u65b9\u304c\u6709\u52b9\u306a\u5834\u5408\u3001\u958b\u59cb\u65e5\u306f\u7d42\u4e86\u65e5\u3088\u308a\u524d\u3067\u3042\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 DateFilterPanel.startCheckBox.text=\u30b9\u30bf\u30fc\u30c8\uff1a DateFilterPanel.startOrEndNeeded.text=\u7bc4\u56f2\u30d5\u30a3\u30eb\u30bf\u30fc\u3092\u4f7f\u7528\u3059\u308b\u306b\u306f\u3001\u958b\u59cb\u65e5\u307e\u305f\u306f\u7d42\u4e86\u65e5\u3092\u6307\u5b9a\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 @@ -63,12 +64,18 @@ DocumentPanel.numberOfImages.noImages=\u753b\u50cf\u306a\u3057 DocumentPanel.numberOfImages.text={0}\u753b\u50cf\u306e1\u3064 DocumentWrapper.previewInitialValue=\u30d7\u30ec\u30d3\u30e5\u30fc\u306f\u307e\u3060\u751f\u6210\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002 DomainDetailsPanel.miniTimelineTitle.text=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3 +DomainDetailsPanel.otherOccurrencesTab.title=\u305d\u306e\u4ed6\u306e\u767a\u751f DomainFilterPanel.domainFiltersSplitPane.border.title=\u30b9\u30c6\u30c3\u30d72\uff1a\u8868\u793a\u3059\u308b\u30c9\u30e1\u30a4\u30f3\u306e\u30d5\u30a3\u30eb\u30bf\u30ea\u30f3\u30b0 DomainSummaryPanel.activity.text=\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3\uff1a{0}\u304b\u3089{1} +DomainSummaryPanel.category.text=\u30ab\u30c6\u30b4\u30ea\uff1a DomainSummaryPanel.downloads.text=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3057\u305f\u30d5\u30a1\u30a4\u30eb\uff1a DomainSummaryPanel.loadingImages.text=\u30b5\u30e0\u30cd\u30a4\u30eb\u3092\u8aad\u307f\u8fbc\u3093\u3067\u3044\u307e\u3059... -DomainSummaryPanel.pages.text=\u904e\u53bb60\u65e5\u9593\u306e\u30da\u30fc\u30b8\u30d3\u30e5\u30fc\uff1a +DomainSummaryPanel.no.text=\u3044\u3044\u3048 +DomainSummaryPanel.notability.text=\u4ee5\u524d\u306b\u6ce8\u76ee\u3059\u3079\u304d\u306b\u30bf\u30b0\u4ed8\u3051\uff1a +DomainSummaryPanel.pages.text=\u6700\u8fd160\u65e5\u9593\u306e\u30da\u30fc\u30b8\u30d3\u30e5\u30fc\uff1a DomainSummaryPanel.totalPages.text=\u5168\u30da\u30fc\u30b8\u30d3\u30e5\u30fc\uff1a +DomainSummaryPanel.userRole.text=\u30a2\u30ab\u30a6\u30f3\u30c8\u30bf\u30a4\u30d7 +DomainSummaryPanel.yes.text=\u306f\u3044 FileDetailsPanel.instancesList.border.title=\u4f8b GroupListPanel.groupKeyList.border.title=\u30b0\u30eb\u30fc\u30d7 GroupsListPanel.noDomainResults.message.text=\u9078\u629e\u3057\u305f\u30d5\u30a3\u30eb\u30bf\u30fc\u3067\u306e\u30c9\u30e1\u30a4\u30f3\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002\n\n\u30ea\u30de\u30a4\u30f3\u30c0\u30fc\uff1a\n -\u6700\u8fd1\u306e\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3\u30e2\u30b8\u30e5\u30fc\u30eb\u3067\u7d50\u679c\u3092\u691c\u7d22\u3059\u308b\u306b\u306f\u5404\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3067\u5b9f\u884c\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002\n -\u904e\u53bb\u306e\u767a\u751f\u3067\u30d5\u30a3\u30eb\u30bf\u30ea\u30f3\u30b0\u307e\u305f\u306f\u30bd\u30fc\u30c8\u3059\u308b\u5834\u5408\u306f\u3001\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u5404\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3067\u5b9f\u884c\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002\n -iOS\u30a2\u30ca\u30e9\u30a4\u30b6\u30fc\uff08iLEAPP\uff09\u30e2\u30b8\u30e5\u30fc\u30eb\u3092iOS\u30c7\u30d0\u30a4\u30b9\u306e\u30c7\u30fc\u30bf\u3092\u542b\u3080\u5404\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3067\u5b9f\u884c\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 diff --git a/Core/src/org/sleuthkit/autopsy/ingest/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/ingest/Bundle_ja.properties index 57e96f90d4..1eb0bcd5aa 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/ingest/Bundle_ja.properties @@ -1,4 +1,4 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Mon Jun 14 12:23:19 UTC 2021 CTL_IngestMessageTopComponent=\u30e1\u30c3\u30bb\u30fc\u30b8 CTL_RunIngestAction=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3092\u5b9f\u884c DataSourceIngestCancellationPanel.cancelAllModulesRadioButton.text=\u3059\u3079\u3066\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u53d6\u308a\u6d88\u3059 @@ -7,6 +7,7 @@ DataSourceIngestPipeline.moduleError.title.text={0} \u30a8\u30e9\u30fc FileIngestCancellationPanel.cancelFileIngestRadioButton.text=\u30d5\u30a1\u30a4\u30eb\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u306e\u307f\u3092\u53d6\u308a\u6d88\u3059 FileIngestCancellationPanel.cancelIngestJobRadioButton.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3068\u30d5\u30a1\u30a4\u30eb\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3092\u53d6\u308a\u6d88\u3059 FileIngestPipeline.moduleError.title.text={0} \u30a8\u30e9\u30fc +FileIngestPipeline_SaveResults_Activity=\u7d50\u679c\u306e\u4fdd\u5b58 HINT_IngestMessageTopComponent=\u30e1\u30c3\u30bb\u30fc\u30b8\u30a6\u30a3\u30f3\u30c9\u30a6 IngestDialog.closeButton.title=\u7d42\u4e86 IngestDialog.startButton.title=\u958b\u59cb diff --git a/Core/src/org/sleuthkit/autopsy/keywordsearchservice/KeywordSearchService.java b/Core/src/org/sleuthkit/autopsy/keywordsearchservice/KeywordSearchService.java index 981abe05de..7d197a4d11 100644 --- a/Core/src/org/sleuthkit/autopsy/keywordsearchservice/KeywordSearchService.java +++ b/Core/src/org/sleuthkit/autopsy/keywordsearchservice/KeywordSearchService.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2015-2019 Basis Technology Corp. + * Copyright 2015-2021 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.keywordsearchservice; +import com.google.common.annotations.Beta; import java.io.Closeable; import java.io.IOException; import org.sleuthkit.autopsy.casemodule.CaseMetadata; @@ -105,5 +106,14 @@ public interface KeywordSearchService extends Closeable { * @throws KeywordSearchServiceException if unable to delete. */ void deleteDataSource(Long dataSourceId) throws KeywordSearchServiceException; + + /** + * A flag to enable or disable OCR on all future text indexing. + * + * @param state Boolean flag to enable/disable OCR. Set to True to enable + * OCR, or False to disable it. + */ + @Beta + void changeOcrState(boolean state); } diff --git a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/SevenZipExtractor.java b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/SevenZipExtractor.java index 35b5a7e560..6fa1e93c5a 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/SevenZipExtractor.java +++ b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/SevenZipExtractor.java @@ -46,6 +46,7 @@ import net.sf.sevenzipjbinding.PropID; import net.sf.sevenzipjbinding.SevenZip; import net.sf.sevenzipjbinding.SevenZipException; import net.sf.sevenzipjbinding.SevenZipNativeInitializationException; +import org.apache.tika.Tika; import org.apache.tika.parser.txt.CharsetDetector; import org.apache.tika.parser.txt.CharsetMatch; import org.netbeans.api.progress.ProgressHandle; @@ -194,6 +195,15 @@ class SevenZipExtractor { } return false; } + + boolean isSevenZipExtractionSupported(String mimeType) { + for (SupportedArchiveExtractionFormats supportedMimeType : SupportedArchiveExtractionFormats.values()) { + if (mimeType.contains(supportedMimeType.toString())) { + return true; + } + } + return false; + } /** * Private helper method to standardize the cancellation check that is @@ -789,33 +799,18 @@ class SevenZipExtractor { // add them to the DB. We wait until the end so that we have the metadata on all of the // intermediate nodes since the order is not guaranteed try { - unpackedTree.updateOrAddFileToCaseRec(statusMap, archiveFilePath); + unpackedTree.updateOrAddFileToCaseRec(statusMap, archiveFilePath, parentAr, archiveFile, depthMap); if (checkForIngestCancellation(archiveFile)) { return false; } - unpackedFiles = unpackedTree.getAllFileObjects(); - //check if children are archives, update archive depth tracking - for (int i = 0; i < unpackedFiles.size(); i++) { - if (checkForIngestCancellation(archiveFile)) { - return false; - } - progress.progress(String.format("%s: Searching for nested archives (%d of %d)", currentArchiveName, i + 1, unpackedFiles.size())); - AbstractFile unpackedFile = unpackedFiles.get(i); - if (unpackedFile == null) { - continue; - } - if (isSevenZipExtractionSupported(unpackedFile)) { - Archive child = new Archive(parentAr.getDepth() + 1, parentAr.getRootArchiveId(), archiveFile); - parentAr.addChild(child); - depthMap.put(unpackedFile.getId(), child); - } - unpackedFile.close(); - } } catch (TskCoreException | NoCurrentCaseException e) { logger.log(Level.SEVERE, "Error populating complete derived file hierarchy from the unpacked dir structure", e); //NON-NLS //TODO decide if anything to cleanup, for now bailing } + + // Get the new files to be added to the case. + unpackedFiles = unpackedTree.getAllFileObjects(); } catch (SevenZipException | IllegalArgumentException ex) { logger.log(Level.WARNING, "Error unpacking file: " + archiveFile, ex); //NON-NLS @@ -991,6 +986,8 @@ class SevenZipExtractor { private EncodedFileOutputStream output; private String localAbsPath; private int bytesWritten; + private static final Tika tika = new Tika(); + private String mimeType = ""; UnpackStream(String localAbsPath) throws IOException { this.output = new EncodedFileOutputStream(new FileOutputStream(localAbsPath), TskData.EncodingType.XOR1); @@ -1003,6 +1000,7 @@ class SevenZipExtractor { this.output = new EncodedFileOutputStream(new FileOutputStream(localAbsPath), TskData.EncodingType.XOR1); this.localAbsPath = localAbsPath; this.bytesWritten = 0; + this.mimeType = ""; } public int getSize() { @@ -1012,6 +1010,10 @@ class SevenZipExtractor { @Override public int write(byte[] bytes) throws SevenZipException { try { + // Detect MIME type now while the file is in memory + if (bytesWritten == 0) { + mimeType = tika.detect(bytes); + } output.write(bytes); this.bytesWritten += bytes.length; } catch (IOException ex) { @@ -1023,6 +1025,10 @@ class SevenZipExtractor { return bytes.length; } + public String getMIMEType() { + return mimeType; + } + public void close() throws IOException { try (EncodedFileOutputStream out = output) { out.flush(); @@ -1196,6 +1202,8 @@ class SevenZipExtractor { 0L, createTimeInSeconds, accessTimeInSeconds, modTimeInSeconds, localRelPath); return; + } else { + unpackedNode.setMimeType(unpackStream.getMIMEType()); } final String localAbsPath = archiveDetailsMap.get( @@ -1413,10 +1421,10 @@ class SevenZipExtractor { * Traverse the tree top-down after unzipping is done and create derived * files for the entire hierarchy */ - void updateOrAddFileToCaseRec(HashMap statusMap, String archiveFilePath) throws TskCoreException, NoCurrentCaseException { + void updateOrAddFileToCaseRec(HashMap statusMap, String archiveFilePath, Archive parentAr, AbstractFile archiveFile, ConcurrentHashMap depthMap) throws TskCoreException, NoCurrentCaseException { final FileManager fileManager = Case.getCurrentCaseThrows().getServices().getFileManager(); for (UnpackedNode child : rootNode.getChildren()) { - updateOrAddFileToCaseRec(child, fileManager, statusMap, archiveFilePath); + updateOrAddFileToCaseRec(child, fileManager, statusMap, archiveFilePath, parentAr, archiveFile, depthMap); } } @@ -1434,7 +1442,7 @@ class SevenZipExtractor { * * @throws TskCoreException */ - private void updateOrAddFileToCaseRec(UnpackedNode node, FileManager fileManager, HashMap statusMap, String archiveFilePath) throws TskCoreException { + private void updateOrAddFileToCaseRec(UnpackedNode node, FileManager fileManager, HashMap statusMap, String archiveFilePath, Archive parentAr, AbstractFile archiveFile, ConcurrentHashMap depthMap) throws TskCoreException { DerivedFile df; progress.progress(String.format("%s: Adding/updating files in case database (%d of %d)", currentArchiveName, ++nodesProcessed, numItems)); try { @@ -1497,10 +1505,17 @@ class SevenZipExtractor { } } } + + // Check for zip bombs + if (isSevenZipExtractionSupported(node.getMimeType())) { + Archive child = new Archive(parentAr.getDepth() + 1, parentAr.getRootArchiveId(), archiveFile); + parentAr.addChild(child); + depthMap.put(node.getFile().getId(), child); + } //recurse adding the children if this file was incomplete the children presumably need to be added for (UnpackedNode child : node.getChildren()) { - updateOrAddFileToCaseRec(child, fileManager, statusMap, getKeyFromUnpackedNode(node, archiveFilePath)); + updateOrAddFileToCaseRec(child, fileManager, statusMap, getKeyFromUnpackedNode(node, archiveFilePath), parentAr, archiveFile, depthMap); } } @@ -1517,6 +1532,7 @@ class SevenZipExtractor { private long size; private long ctime, crtime, atime, mtime; private boolean isFile; + private String mimeType = ""; private UnpackedNode parent; //root constructor @@ -1593,6 +1609,14 @@ class SevenZipExtractor { void setFile(AbstractFile file) { this.file = file; } + + void setMimeType(String mimeType) { + this.mimeType = mimeType; + } + + String getMimeType() { + return mimeType; + } /** * get child by name or null if it doesn't exist diff --git a/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/Bundle_ja.properties index 984ae6bb6f..c2aa0bce4a 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/Bundle_ja.properties @@ -1,4 +1,4 @@ -#Fri Feb 12 16:56:29 UTC 2021 +#Mon Jun 14 12:23:19 UTC 2021 ALeappAnalyzerIngestModule.aLeapp.cancelled=aLeapp\u5b9f\u884c\u304c\u30ad\u30e3\u30f3\u30bb\u30eb\u3055\u308c\u307e\u3057\u305f ALeappAnalyzerIngestModule.completed=aLeapp\u51e6\u7406\u304c\u5b8c\u4e86\u3057\u307e\u3057\u305f ALeappAnalyzerIngestModule.error.creating.output.dir=aLeapp\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u51fa\u529b\u30d5\u30a9\u30eb\u30c0\u30fc\u306e\u4f5c\u6210\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 @@ -16,6 +16,7 @@ ALeappAnalyzerIngestModule.running.aLeapp=aLeapp\u5b9f\u884c\u4e2d ALeappAnalyzerIngestModule.starting.aLeapp=aLeapp\u306e\u958b\u59cb ALeappAnalyzerModuleFactory_moduleDesc=aLEAPP\u3092\u4f7f\u7528\u3057\u3066\u3001Android\u30c7\u30d0\u30a4\u30b9\u306e\u8ad6\u7406\u7684\u306a\u53d6\u5f97\u3092\u5206\u6790\u3057\u307e\u3059\u3002 ALeappAnalyzerModuleFactory_moduleName=Android\u30a2\u30ca\u30e9\u30a4\u30b6\u30fc\uff08aLEAPP\uff09 +AleappAnalyzerIngestModule.not.64.bit.os=aLeapp\u306f32\u30d3\u30c3\u30c8\u30aa\u30da\u30ec\u30fc\u30c6\u30a3\u30f3\u30b0\u30b7\u30b9\u30c6\u30e0\u3067\u306f\u5b9f\u884c\u3055\u308c\u307e\u305b\u3093 ILeappAnalyzerIngestModule.completed=iLeapp\u51e6\u7406\u304c\u5b8c\u4e86\u3057\u307e\u3057\u305f ILeappAnalyzerIngestModule.error.creating.output.dir=iLeapp\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u51fa\u529b\u30d5\u30a9\u30eb\u30c0\u30fc\u306e\u4f5c\u6210\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 ILeappAnalyzerIngestModule.error.ileapp.file.processor.init=ILeappProcessFile\u306e\u521d\u671f\u5316\u306b\u5931\u6557\u3057\u307e\u3057\u305f @@ -33,8 +34,10 @@ ILeappAnalyzerIngestModule.running.iLeapp=iLeapp\u5b9f\u884c\u4e2d ILeappAnalyzerIngestModule.starting.iLeapp=iLeapp\u306e\u958b\u59cb ILeappAnalyzerModuleFactory_moduleDesc=iLEAPP\u3092\u4f7f\u7528\u3057\u3066\u3001iOS\u30c7\u30d0\u30a4\u30b9\u306e\u8ad6\u7406\u7684\u306a\u53d6\u5f97\u3092\u5206\u6790\u3057\u307e\u3059\u3002 ILeappAnalyzerModuleFactory_moduleName=iOS\u30a2\u30ca\u30e9\u30a4\u30b6\u30fc\uff08iLEAPP\uff09 +IleappAnalyzerIngestModule.not.64.bit.os=iLeapp\u306f32\u30d3\u30c3\u30c8\u30aa\u30da\u30ec\u30fc\u30c6\u30a3\u30f3\u30b0\u30b7\u30b9\u30c6\u30e0\u3067\u306f\u5b9f\u884c\u3055\u308c\u307e\u305b\u3093 LeappFileProcessor.Leapp.cancelled=Leapp\u5b9f\u884c\u304c\u30ad\u30e3\u30f3\u30bb\u30eb\u3055\u308c\u307e\u3057\u305f -LeappFileProcessor.cannot.load.artifact.xml=xml\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u30d5\u30a1\u30a4\u30eb\u3092\u8aad\u307f\u8fbc\u3081\u307e\u305b\u3093\u3002 +LeappFileProcessor.cannot.create.message.relationship=TSK_MESSAGE\u95a2\u4fc2\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3002 +LeappFileProcessor.cannot.load.artifact.xml=xml\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u30fb\u30d5\u30a1\u30a4\u30eb\u3092\u8aad\u307f\u8fbc\u3081\u307e\u305b\u3093\u3002 LeappFileProcessor.cannotBuildXmlParser=XML\u30d1\u30fc\u30b5\u30fc\u3092\u69cb\u7bc9\u3067\u304d\u307e\u305b\u3093\u3002 LeappFileProcessor.completed=Leapp\u51e6\u7406\u304c\u5b8c\u4e86\u3057\u307e\u3057\u305f LeappFileProcessor.error.creating.new.artifacts=\u65b0\u3057\u3044\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u306e\u4f5c\u6210\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 diff --git a/Core/src/org/sleuthkit/autopsy/url/analytics/domaincategorization/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/url/analytics/domaincategorization/Bundle_ja.properties new file mode 100644 index 0000000000..a670858371 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/url/analytics/domaincategorization/Bundle_ja.properties @@ -0,0 +1,35 @@ +#Mon Jun 14 12:23:19 UTC 2021 +AddEditCategoryDialog.cancelButton.text=\u30ad\u30e3\u30f3\u30bb\u30eb +AddEditCategoryDialog.categoryLabel.text=\u30ab\u30c6\u30b4\u30ea\u30fc\uff1a +AddEditCategoryDialog.domainSuffixLabel.text=\u30c9\u30e1\u30a4\u30f3\u30fb\u30b5\u30d5\u30a3\u30c3\u30af\u30b9\uff1a +AddEditCategoryDialog.saveButton.text=\u4fdd\u5168 +AddEditCategoryDialog_Add=\u30a8\u30f3\u30c8\u30ea\u3092\u8ffd\u52a0 +AddEditCategoryDialog_Edit=\u30a8\u30f3\u30c8\u30ea\u306e\u7de8\u96c6 +AddEditCategoryDialog_onValueUpdate_badCategory={0}\u6587\u5b57\u4ee5\u4e0b\u306e\u30ab\u30c6\u30b4\u30ea\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +AddEditCategoryDialog_onValueUpdate_badSuffix=1\u3064\u4ee5\u4e0a\u306e\u30d4\u30ea\u30aa\u30c9\u3092\u542b\u3080{0}\u6587\u5b57\u4ee5\u4e0b\u306e\u30c9\u30e1\u30a4\u30f3\u30b5\u30d5\u30a3\u30c3\u30af\u30b9\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +AddEditCategoryDialog_onValueUpdate_sameCategory=\u3053\u306e\u30c9\u30e1\u30a4\u30f3\u30b5\u30d5\u30a3\u30c3\u30af\u30b9\u306e\u65b0\u3057\u3044\u30ab\u30c6\u30b4\u30ea\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +AddEditCategoryDialog_onValueUpdate_suffixRepeat=\u30e6\u30cb\u30fc\u30af\u306e\u30c9\u30e1\u30a4\u30f3\u30fb\u30b5\u30d5\u30a3\u30c3\u30af\u30b9\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u30fb +WebCategoriesOptionsPanel.categoriesTitle.text=\u30ab\u30c6\u30b4\u30ea\uff1a +WebCategoriesOptionsPanel.deleteEntryButton.text=\u30a8\u30f3\u30c8\u30ea\u3092\u524a\u9664 +WebCategoriesOptionsPanel.editEntryButton.text=\u30a8\u30f3\u30c8\u30ea\u306e\u7de8\u96c6 +WebCategoriesOptionsPanel.exportSetButton.text=\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u30fb\u30bb\u30c3\u30c8 +WebCategoriesOptionsPanel.importSetButton.text=\u30a4\u30f3\u30dd\u30fc\u30c8\u30fb\u30bb\u30c3\u30c8 +WebCategoriesOptionsPanel.ingestRunningWarning.text=\u53d6\u8fbc\u307f\u306f\u73fe\u5728\u5b9f\u884c\u4e2d\u3067\u3059\u3002 \u4eca\u306f\u7de8\u96c6\u306f\u3067\u304d\u307e\u305b\u3093\u3002 +WebCategoriesOptionsPanel.newEntryButton.text=\u65b0\u898f\u30a8\u30f3\u30c8\u30ea\u30fc +WebCategoriesOptionsPanel.panelDescription.text=\u3053\u306e\u6a5f\u80fd\u3092\u4f7f\u7528\u3059\u308b\u3068\u3001\u6700\u8fd1\u306e\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3\u306e\u53d6\u8fbc\u307f\u30e2\u30b8\u30e5\u30fc\u30eb\u3067\u3001\u30c9\u30e1\u30a4\u30f3\u306e\u30b5\u30d5\u30a3\u30c3\u30af\u30b9\u306b\u57fa\u3065\u3044\u3066Web\u30b5\u30a4\u30c8\u306e\u30ab\u30b9\u30bf\u30e0\u5206\u985e\u3092\u5b9f\u884c\u3067\u304d\u307e\u3059\u3002 +WebCategoriesOptionsPanel_categoryTable_categoryColumnName=\u30ab\u30c6\u30b4\u30ea\uff1a +WebCategoriesOptionsPanel_categoryTable_suffixColumnName=\u30c9\u30e1\u30a4\u30f3\u30fb\u30b5\u30d5\u30a3\u30c3\u30af\u30b9 +WebCategoriesOptionsPanel_exportSetButtonActionPerformed_defaultFileName=\u30ab\u30b9\u30bf\u30e0\u30fb\u30ab\u30c6\u30b4\u30ea\u306e\u30a8\u30af\u30b9\u30dd\u30fc\u30c8 +WebCategoriesOptionsPanel_exportSetButtonActionPerformed_duplicateMessage=\u9078\u629e\u3057\u305f\u30d1\u30b9\u306b\u30d5\u30a1\u30a4\u30eb\u304c\u65e2\u306b\u5b58\u5728\u3057\u307e\u3059\u3002 \u30ab\u30c6\u30b4\u30ea\u306f\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u3055\u308c\u307e\u305b\u3093\u3002 +WebCategoriesOptionsPanel_exportSetButtonActionPerformed_duplicateTitle=\u30d5\u30a1\u30a4\u30eb\u304c\u65e2\u306b\u5b58\u5728\u3057\u307e\u3059 +WebCategoriesOptionsPanel_exportSetButtonActionPerformed_errorMessage=\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +WebCategoriesOptionsPanel_exportSetButtonActionPerformed_errorTitle=\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u30a8\u30e9\u30fc +WebCategoriesOptionsPanel_importSetButtonActionPerformed_errorMessage=json\u30d5\u30a1\u30a4\u30eb\u306e\u30a4\u30f3\u30dd\u30fc\u30c8\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +WebCategoriesOptionsPanel_importSetButtonActionPerformed_errorTitle=\u30a4\u30f3\u30dd\u30fc\u30c8\u30a8\u30e9\u30fc +WebCategoriesOptionsPanel_importSetButtonActionPerformed_onConflictCancel=\u30ad\u30e3\u30f3\u30bb\u30eb +WebCategoriesOptionsPanel_importSetButtonActionPerformed_onConflictMessage=\u30c9\u30e1\u30a4\u30f3\u30b5\u30d5\u30a3\u30c3\u30af\u30b9{0}\u306f\u3059\u3067\u306b\u5b58\u5728\u3057\u307e\u3059\u3002 \u4f55\u3092\u3057\u307e\u3059\u304b\uff1f +WebCategoriesOptionsPanel_importSetButtonActionPerformed_onConflictOverwrite=\u4e0a\u66f8\u304d\u3059\u308b +WebCategoriesOptionsPanel_importSetButtonActionPerformed_onConflictSkip=\u7121\u8996 +WebCategoriesOptionsPanel_importSetButtonActionPerformed_onConflictTitle=\u30c9\u30e1\u30a4\u30f3\u30fb\u30b5\u30d5\u30a3\u30c3\u30af\u30b9\u306f\u3059\u3067\u306b\u5b58\u5728\u3057\u307e\u3059 +WebCategoryOptionsController_keywords=\u30ab\u30b9\u30bf\u30e0Web\u30ab\u30c6\u30b4\u30ea +WebCategoryOptionsController_title=\u30ab\u30b9\u30bf\u30e0Web\u30ab\u30c6\u30b4\u30ea diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AinStatusNode.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AinStatusNode.java index 8c7ba7cdd9..9d72539841 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AinStatusNode.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AinStatusNode.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2018 Basis Technology Corp. + * Copyright 2018-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -40,7 +40,7 @@ final class AinStatusNode extends AbstractNode { * Construct a new AinStatusNode. */ AinStatusNode(AutoIngestMonitor monitor) { - super(Children.create(new AinStatusChildren(monitor), false)); + super(Children.create(new AinStatusChildren(monitor), true)); } /** diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestAdminActions.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestAdminActions.java index a881a96fb2..6680074a17 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestAdminActions.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestAdminActions.java @@ -157,6 +157,102 @@ final class AutoIngestAdminActions { } } } + + @NbBundle.Messages({"AutoIngestAdminActions.enableOCR.title=Enable OCR For This Case", + "AutoIngestAdminActions.enableOCR.error=Failed to enable OCR for case \"%s\"."}) + static final class EnableOCR extends AbstractAction { + + private static final long serialVersionUID = 1L; + private final AutoIngestJob job; + + EnableOCR(AutoIngestJob job) { + super(Bundle.AutoIngestAdminActions_enableOCR_title()); + this.job = job; + } + + @Override + public void actionPerformed(ActionEvent e) { + + if (job == null) { + return; + } + + final AutoIngestDashboardTopComponent tc = (AutoIngestDashboardTopComponent) WindowManager.getDefault().findTopComponent(AutoIngestDashboardTopComponent.PREFERRED_ID); + if (tc == null) { + return; + } + + AutoIngestDashboard dashboard = tc.getAutoIngestDashboard(); + if (dashboard != null) { + dashboard.getPendingJobsPanel().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + EventQueue.invokeLater(() -> { + try { + dashboard.getMonitor().changeOcrStateForCase(job.getManifest().getCaseName(), true); + dashboard.getPendingJobsPanel().refresh(new AutoIngestNodeRefreshEvents.RefreshCaseEvent(dashboard.getMonitor(), job.getManifest().getCaseName())); + } catch (AutoIngestMonitor.AutoIngestMonitorException ex) { + String errorMessage = String.format(Bundle.AutoIngestAdminActions_enableOCR_error(), job.getManifest().getCaseName()); + logger.log(Level.SEVERE, errorMessage, ex); + MessageNotifyUtil.Message.error(errorMessage); + } finally { + dashboard.getPendingJobsPanel().setCursor(Cursor.getDefaultCursor()); + } + }); + } + } + + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); //To change body of generated methods, choose Tools | Templates. + } + } + + @NbBundle.Messages({"AutoIngestAdminActions.disableOCR.title=Disable OCR For This Case", + "AutoIngestAdminActions.disableOCR.error=Failed to disable OCR for case \"%s\"."}) + static final class DisableOCR extends AbstractAction { + + private static final long serialVersionUID = 1L; + private final AutoIngestJob job; + + DisableOCR(AutoIngestJob job) { + super(Bundle.AutoIngestAdminActions_disableOCR_title()); + this.job = job; + } + + @Override + public void actionPerformed(ActionEvent e) { + + if (job == null) { + return; + } + + final AutoIngestDashboardTopComponent tc = (AutoIngestDashboardTopComponent) WindowManager.getDefault().findTopComponent(AutoIngestDashboardTopComponent.PREFERRED_ID); + if (tc == null) { + return; + } + + AutoIngestDashboard dashboard = tc.getAutoIngestDashboard(); + if (dashboard != null) { + dashboard.getPendingJobsPanel().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + EventQueue.invokeLater(() -> { + try { + dashboard.getMonitor().changeOcrStateForCase(job.getManifest().getCaseName(), false); + dashboard.getPendingJobsPanel().refresh(new AutoIngestNodeRefreshEvents.RefreshCaseEvent(dashboard.getMonitor(), job.getManifest().getCaseName())); + } catch (AutoIngestMonitor.AutoIngestMonitorException ex) { + String errorMessage = String.format(Bundle.AutoIngestAdminActions_disableOCR_error(), job.getManifest().getCaseName()); + logger.log(Level.SEVERE, errorMessage, ex); + MessageNotifyUtil.Message.error(errorMessage); + } finally { + dashboard.getPendingJobsPanel().setCursor(Cursor.getDefaultCursor()); + } + }); + } + } + + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); //To change body of generated methods, choose Tools | Templates. + } + } @NbBundle.Messages({"AutoIngestAdminActions.progressDialogAction.title=Ingest Progress"}) static final class ProgressDialogAction extends AbstractAction { diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java index 0e25ca655f..656b98b278 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2015-2018 Basis Technology Corp. + * Copyright 2015-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -122,6 +122,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { private static final int RUNNING_TABLE_COL_PREFERRED_WIDTH = 175; private static final int PRIORITY_COLUMN_PREFERRED_WIDTH = 60; private static final int PRIORITY_COLUMN_MAX_WIDTH = 150; + private static final int OCR_COLUMN_PREFERRED_WIDTH = 50; + private static final int OCR_COLUMN_MAX_WIDTH = 150; private static final int ACTIVITY_TIME_COL_MIN_WIDTH = 250; private static final int ACTIVITY_TIME_COL_MAX_WIDTH = 450; private static final int TIME_COL_MIN_WIDTH = 30; @@ -133,9 +135,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { private static final int ACTIVITY_COL_MIN_WIDTH = 70; private static final int ACTIVITY_COL_MAX_WIDTH = 2000; private static final int ACTIVITY_COL_PREFERRED_WIDTH = 300; - private static final int STATUS_COL_MIN_WIDTH = 55; + private static final int STATUS_COL_MIN_WIDTH = 50; private static final int STATUS_COL_MAX_WIDTH = 250; - private static final int STATUS_COL_PREFERRED_WIDTH = 55; + private static final int STATUS_COL_PREFERRED_WIDTH = 50; private static final int COMPLETED_TIME_COL_MIN_WIDTH = 30; private static final int COMPLETED_TIME_COL_MAX_WIDTH = 2000; private static final int COMPLETED_TIME_COL_PREFERRED_WIDTH = 280; @@ -179,7 +181,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { "AutoIngestControlPanel.JobsTableModel.ColumnHeader.Status=Status", "AutoIngestControlPanel.JobsTableModel.ColumnHeader.CaseFolder=Case Folder", "AutoIngestControlPanel.JobsTableModel.ColumnHeader.LocalJob= Local Job?", - "AutoIngestControlPanel.JobsTableModel.ColumnHeader.ManifestFilePath= Manifest File Path" + "AutoIngestControlPanel.JobsTableModel.ColumnHeader.ManifestFilePath= Manifest File Path", + "AutoIngestControlPanel.JobsTableModel.ColumnHeader.OCR=OCR" }) private enum JobsTableModelColumns { @@ -195,7 +198,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { CASE_DIRECTORY_PATH(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.CaseFolder")), IS_LOCAL_JOB(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.LocalJob")), MANIFEST_FILE_PATH(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.ManifestFilePath")), - PRIORITY(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.Priority")); + PRIORITY(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.Priority")), + OCR(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.OCR")); private final String header; private JobsTableModelColumns(String header) { @@ -219,7 +223,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { CASE_DIRECTORY_PATH.getColumnHeader(), IS_LOCAL_JOB.getColumnHeader(), MANIFEST_FILE_PATH.getColumnHeader(), - PRIORITY.getColumnHeader()}; + PRIORITY.getColumnHeader(), + OCR.getColumnHeader()}; } /** @@ -406,6 +411,12 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { column.setMaxWidth(PRIORITY_COLUMN_MAX_WIDTH); column.setPreferredWidth(PRIORITY_COLUMN_PREFERRED_WIDTH); column.setWidth(PRIORITY_COLUMN_PREFERRED_WIDTH); + + column = pendingTable.getColumn(JobsTableModelColumns.OCR.getColumnHeader()); + column.setCellRenderer(new OcrIconCellRenderer()); + column.setMaxWidth(OCR_COLUMN_MAX_WIDTH); + column.setPreferredWidth(OCR_COLUMN_PREFERRED_WIDTH); + column.setWidth(OCR_COLUMN_PREFERRED_WIDTH); /** * Allow sorting when a column header is clicked. @@ -457,6 +468,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.IS_LOCAL_JOB.getColumnHeader())); runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.MANIFEST_FILE_PATH.getColumnHeader())); runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.PRIORITY.getColumnHeader())); + runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.OCR.getColumnHeader())); + /* * Set up a column to display the cases associated with the jobs. */ @@ -553,6 +566,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.CASE_DIRECTORY_PATH.getColumnHeader())); completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.MANIFEST_FILE_PATH.getColumnHeader())); completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.PRIORITY.getColumnHeader())); + /* * Set up a column to display the cases associated with the jobs. */ @@ -603,6 +617,15 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { column.setMaxWidth(STATUS_COL_MAX_WIDTH); column.setPreferredWidth(STATUS_COL_PREFERRED_WIDTH); column.setWidth(STATUS_COL_PREFERRED_WIDTH); + + /* + * Set up a column to display OCR enabled/disabled flag. + */ + column = completedTable.getColumn(JobsTableModelColumns.OCR.getColumnHeader()); + column.setCellRenderer(new OcrIconCellRenderer()); + column.setMaxWidth(OCR_COLUMN_MAX_WIDTH); + column.setPreferredWidth(OCR_COLUMN_PREFERRED_WIDTH); + column.setWidth(OCR_COLUMN_PREFERRED_WIDTH); /* * Allow sorting when a column header is clicked. @@ -856,6 +879,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { case JOB_COMPLETED: case CASE_DELETED: case REPROCESS_JOB: + case OCR_STATE_CHANGE: updateExecutor.submit(new UpdateAllJobsTablesTask()); break; case PAUSED_BY_USER_REQUEST: @@ -1193,7 +1217,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { job.getCaseDirectoryPath(), // CASE_DIRECTORY_PATH job.getProcessingHostName().equals(LOCAL_HOST_NAME), // IS_LOCAL_JOB job.getManifest().getFilePath(), // MANIFEST_FILE_PATH - job.getPriority()}); // PRIORITY + job.getPriority(), // PRIORITY + job.getOcrEnabled()}); // OCR FLAG } } catch (Exception ex) { sysLogger.log(Level.SEVERE, "Dashboard error refreshing table", ex); diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJob.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJob.java index 68487d0fcb..a1ce23b917 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJob.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJob.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2018 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -46,7 +46,7 @@ import org.sleuthkit.autopsy.ingest.IngestProgressSnapshotProvider; final class AutoIngestJob implements Comparable, IngestProgressSnapshotProvider, Serializable { private static final long serialVersionUID = 1L; - private static final int CURRENT_VERSION = 3; + private static final int CURRENT_VERSION = 4; private static final int DEFAULT_PRIORITY = 0; private static final String LOCAL_HOST_NAME = NetworkUtils.getLocalHostName(); @@ -100,6 +100,11 @@ final class AutoIngestJob implements Comparable, IngestProgressSn private List ingestThreadsSnapshot; private List ingestJobsSnapshot; private Map moduleRunTimesSnapshot; + + /* + * Version 4 fields. + */ + private boolean ocrEnabled; /** * Constructs a new automated ingest job. All job state not specified in the @@ -194,6 +199,11 @@ final class AutoIngestJob implements Comparable, IngestProgressSn this.ingestJobsSnapshot = Collections.emptyList(); this.moduleRunTimesSnapshot = Collections.emptyMap(); + /* + * Version 4 fields + */ + this.ocrEnabled = nodeData.getOcrEnabled(); + } catch (Exception ex) { throw new AutoIngestJobException(String.format("Error creating automated ingest job"), ex); } @@ -253,6 +263,24 @@ final class AutoIngestJob implements Comparable, IngestProgressSn synchronized Integer getPriority() { return this.priority; } + + /** + * Gets the OCR flag for the job. + * + * @return Flag whether OCR is enabled/disabled. + */ + synchronized boolean getOcrEnabled() { + return this.ocrEnabled; + } + + /** + * Sets the OCR enabled/disabled flag for the job. + * + * @param enabled Flag whether OCR is enabled/disabled. + */ + synchronized void setOcrEnabled(boolean enabled) { + this.ocrEnabled = enabled; + } /** * Sets the processing stage of the job. The start date/time for the stage diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java index f367fdf553..5e9ab8955d 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2017 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -31,7 +31,7 @@ import javax.lang.model.type.TypeKind; */ final class AutoIngestJobNodeData { - private static final int CURRENT_VERSION = 2; + private static final int CURRENT_VERSION = 3; private static final int DEFAULT_PRIORITY = 0; /* @@ -47,7 +47,7 @@ final class AutoIngestJobNodeData { * data. This avoids the need to continuously enlarge the buffer. Once the * buffer has all the necessary data, it will be resized as appropriate. */ - private static final int MAX_POSSIBLE_NODE_DATA_SIZE = 131637; + private static final int MAX_POSSIBLE_NODE_DATA_SIZE = 131641; /* * Version 0 fields. @@ -78,6 +78,11 @@ final class AutoIngestJobNodeData { * Version 2 fields. */ private long dataSourceSize; + + /* + * Version 3 fields. + */ + private boolean ocrEnabled; /** * Gets the current version of the auto ingest job coordination service node @@ -115,6 +120,7 @@ final class AutoIngestJobNodeData { setProcessingStageStartDate(job.getProcessingStageStartDate()); setProcessingStageDetails(job.getProcessingStageDetails()); setDataSourceSize(job.getDataSourceSize()); + setOcrEnabled(job.getOcrEnabled()); } /** @@ -128,7 +134,7 @@ final class AutoIngestJobNodeData { if (null == nodeData || nodeData.length == 0) { throw new InvalidDataException(null == nodeData ? "Null nodeData byte array" : "Zero-length nodeData byte array"); } - + /* * Set default values for all fields. */ @@ -150,6 +156,7 @@ final class AutoIngestJobNodeData { this.processingStageDetailsDescription = ""; this.processingStageDetailsStartDate = 0L; this.dataSourceSize = 0L; + this.ocrEnabled = false; /* * Get fields from node data. @@ -192,6 +199,14 @@ final class AutoIngestJobNodeData { */ this.dataSourceSize = buffer.getLong(); } + + if (buffer.hasRemaining()) { + /* + * Get version 3 fields. + */ + int ocrFlag = buffer.getInt(); + this.ocrEnabled = (1 == ocrFlag); + } } catch (BufferUnderflowException ex) { throw new InvalidDataException("Node data is incomplete", ex); @@ -234,6 +249,24 @@ final class AutoIngestJobNodeData { void setPriority(int priority) { this.priority = priority; } + + /** + * Gets the OCR flag for the job. + * + * @return Flag whether OCR is enabled/disabled. + */ + boolean getOcrEnabled() { + return this.ocrEnabled; + } + + /** + * Sets the OCR enabled/disabled flag for the job. + * + * @param enabled Flag whether OCR is enabled/disabled. + */ + void setOcrEnabled(boolean enabled) { + this.ocrEnabled = enabled; + } /** * Gets the number of times the job has crashed during processing. @@ -567,6 +600,10 @@ final class AutoIngestJobNodeData { if (this.version >= 2) { buffer.putLong(this.dataSourceSize); } + + if (this.version >= 3) { + buffer.putInt(this.ocrEnabled ? 1 : 0); + } } // Prepare the array diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java index ffe8e19f01..415b3237b9 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2018-2019 Basis Technology Corp. + * Copyright 2018-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -57,7 +57,8 @@ final class AutoIngestJobsNode extends AbstractNode { "AutoIngestJobsNode.jobCreated.text=Job Created", "AutoIngestJobsNode.jobCompleted.text=Job Completed", "AutoIngestJobsNode.priority.text=Prioritized", - "AutoIngestJobsNode.status.text=Status" + "AutoIngestJobsNode.status.text=Status", + "AutoIngestJobsNode.ocr.text=OCR" }) /** @@ -69,7 +70,7 @@ final class AutoIngestJobsNode extends AbstractNode { * refresh events */ AutoIngestJobsNode(AutoIngestMonitor monitor, AutoIngestJobStatus status, EventBus eventBus) { - super(Children.create(new AutoIngestNodeChildren(monitor, status, eventBus), false)); + super(Children.create(new AutoIngestNodeChildren(monitor, status, eventBus), true)); refreshChildrenEventBus = eventBus; } @@ -98,12 +99,14 @@ final class AutoIngestJobsNode extends AbstractNode { private final Stage jobStage; private final List jobSnapshot; private final Integer jobPriority; + private final Boolean ocrFlag; AutoIngestJobWrapper(AutoIngestJob job) { autoIngestJob = job; jobStage = job.getProcessingStage(); jobSnapshot = job.getIngestJobSnapshots(); jobPriority = job.getPriority(); + ocrFlag = job.getOcrEnabled(); } AutoIngestJob getJob() { @@ -123,11 +126,12 @@ final class AutoIngestJobsNode extends AbstractNode { AutoIngestJob thisJob = this.autoIngestJob; AutoIngestJob otherJob = ((AutoIngestJobWrapper) other).autoIngestJob; - // Only equal if the manifest paths and processing stage details are the same. + // Only equal if the manifest paths, processing stage details, priority, and OCR flag are the same. return thisJob.getManifest().getFilePath().equals(otherJob.getManifest().getFilePath()) && jobStage.equals(((AutoIngestJobWrapper) other).jobStage) && jobSnapshot.equals(((AutoIngestJobWrapper) other).jobSnapshot) - && jobPriority.equals(((AutoIngestJobWrapper) other).jobPriority); + && jobPriority.equals(((AutoIngestJobWrapper) other).jobPriority) + && ocrFlag.equals(((AutoIngestJobWrapper) other).ocrFlag); } @Override @@ -137,6 +141,7 @@ final class AutoIngestJobsNode extends AbstractNode { hash = 23 * hash + Objects.hashCode(this.jobStage); hash = 23 * hash + Objects.hashCode(this.jobSnapshot); hash = 23 * hash + Objects.hashCode(this.jobPriority); + hash = 23 * hash + Objects.hashCode(this.ocrFlag); return hash; } @@ -171,6 +176,10 @@ final class AutoIngestJobsNode extends AbstractNode { Integer getPriority() { return autoIngestJob.getPriority(); } + + boolean getOcrEnabled() { + return autoIngestJob.getOcrEnabled(); + } } /** @@ -327,6 +336,8 @@ final class AutoIngestJobsNode extends AbstractNode { jobWrapper.getManifest().getDateFileCreated())); ss.put(new NodeProperty<>(Bundle.AutoIngestJobsNode_priority_text(), Bundle.AutoIngestJobsNode_priority_text(), Bundle.AutoIngestJobsNode_priority_text(), jobWrapper.getPriority())); + ss.put(new NodeProperty<>(Bundle.AutoIngestJobsNode_ocr_text(), Bundle.AutoIngestJobsNode_ocr_text(), Bundle.AutoIngestJobsNode_ocr_text(), + jobWrapper.getOcrEnabled())); break; case RUNNING_JOB: AutoIngestJob.StageDetails status = jobWrapper.getProcessingStageDetails(); @@ -344,6 +355,8 @@ final class AutoIngestJobsNode extends AbstractNode { jobWrapper.getCompletedDate())); ss.put(new NodeProperty<>(Bundle.AutoIngestJobsNode_status_text(), Bundle.AutoIngestJobsNode_status_text(), Bundle.AutoIngestJobsNode_status_text(), jobWrapper.getErrorsOccurred() ? StatusIconCellRenderer.Status.WARNING : StatusIconCellRenderer.Status.OK)); + ss.put(new NodeProperty<>(Bundle.AutoIngestJobsNode_ocr_text(), Bundle.AutoIngestJobsNode_ocr_text(), Bundle.AutoIngestJobsNode_ocr_text(), + jobWrapper.getOcrEnabled())); break; default: } @@ -364,6 +377,11 @@ final class AutoIngestJobsNode extends AbstractNode { PrioritizationAction.DeprioritizeCaseAction deprioritizeCaseAction = new PrioritizationAction.DeprioritizeCaseAction(jobWrapper.getJob()); deprioritizeCaseAction.setEnabled(jobWrapper.getPriority() > 0); actions.add(deprioritizeCaseAction); + + actions.add(new AutoIngestAdminActions.EnableOCR(jobWrapper.getJob())); + AutoIngestAdminActions.DisableOCR disableOCRAction = new AutoIngestAdminActions.DisableOCR(jobWrapper.getJob()); + disableOCRAction.setEnabled(jobWrapper.getOcrEnabled() == true); + actions.add(disableOCRAction); break; case RUNNING_JOB: actions.add(new AutoIngestAdminActions.ProgressDialogAction(jobWrapper.getJob())); diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsPanel.java index 6962057541..d335a35430 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2018 Basis Technology Corp. + * Copyright 2018-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -43,6 +43,7 @@ final class AutoIngestJobsPanel extends javax.swing.JPanel implements ExplorerMa private static final int INITIAL_CASENAME_WIDTH = 170; private static final int INITIAL_DATASOURCE_WIDTH = 270; private static final int INITIAL_PRIORITIZED_WIDTH = 20; + private static final int INITIAL_OCR_WIDTH = 20; private static final int INITIAL_STATUS_WIDTH = 20; private static final int INVALID_INDEX = -1; private final org.openide.explorer.view.OutlineView outlineView; @@ -81,12 +82,18 @@ final class AutoIngestJobsPanel extends javax.swing.JPanel implements ExplorerMa case PENDING_JOB: outlineView.setPropertyColumns(Bundle.AutoIngestJobsNode_dataSource_text(), Bundle.AutoIngestJobsNode_dataSource_text(), Bundle.AutoIngestJobsNode_jobCreated_text(), Bundle.AutoIngestJobsNode_jobCreated_text(), - Bundle.AutoIngestJobsNode_priority_text(), Bundle.AutoIngestJobsNode_priority_text()); + Bundle.AutoIngestJobsNode_priority_text(), Bundle.AutoIngestJobsNode_priority_text(), + Bundle.AutoIngestJobsNode_ocr_text(), Bundle.AutoIngestJobsNode_ocr_text()); indexOfColumn = getColumnIndexByName(Bundle.AutoIngestJobsNode_priority_text()); if (indexOfColumn != INVALID_INDEX) { outline.getColumnModel().getColumn(indexOfColumn).setPreferredWidth(INITIAL_PRIORITIZED_WIDTH); outline.getColumnModel().getColumn(indexOfColumn).setCellRenderer(new PrioritizedIconCellRenderer()); } + indexOfColumn = getColumnIndexByName(Bundle.AutoIngestJobsNode_ocr_text()); + if (indexOfColumn != INVALID_INDEX) { + outline.getColumnModel().getColumn(indexOfColumn).setPreferredWidth(INITIAL_OCR_WIDTH); + outline.getColumnModel().getColumn(indexOfColumn).setCellRenderer(new OcrIconCellRenderer()); + } break; case RUNNING_JOB: outlineView.setPropertyColumns(Bundle.AutoIngestJobsNode_dataSource_text(), Bundle.AutoIngestJobsNode_dataSource_text(), @@ -102,7 +109,8 @@ final class AutoIngestJobsPanel extends javax.swing.JPanel implements ExplorerMa outlineView.setPropertyColumns(Bundle.AutoIngestJobsNode_dataSource_text(), Bundle.AutoIngestJobsNode_dataSource_text(), Bundle.AutoIngestJobsNode_jobCreated_text(), Bundle.AutoIngestJobsNode_jobCreated_text(), Bundle.AutoIngestJobsNode_jobCompleted_text(), Bundle.AutoIngestJobsNode_jobCompleted_text(), - Bundle.AutoIngestJobsNode_status_text(), Bundle.AutoIngestJobsNode_status_text()); + Bundle.AutoIngestJobsNode_status_text(), Bundle.AutoIngestJobsNode_status_text(), + Bundle.AutoIngestJobsNode_ocr_text(), Bundle.AutoIngestJobsNode_ocr_text()); indexOfColumn = getColumnIndexByName(Bundle.AutoIngestJobsNode_jobCompleted_text()); if (indexOfColumn != INVALID_INDEX) { outline.setColumnSorted(indexOfColumn, false, 1); @@ -112,6 +120,11 @@ final class AutoIngestJobsPanel extends javax.swing.JPanel implements ExplorerMa outline.getColumnModel().getColumn(indexOfColumn).setPreferredWidth(INITIAL_STATUS_WIDTH); outline.getColumnModel().getColumn(indexOfColumn).setCellRenderer(new StatusIconCellRenderer()); } + indexOfColumn = getColumnIndexByName(Bundle.AutoIngestJobsNode_ocr_text()); + if (indexOfColumn != INVALID_INDEX) { + outline.getColumnModel().getColumn(indexOfColumn).setPreferredWidth(INITIAL_OCR_WIDTH); + outline.getColumnModel().getColumn(indexOfColumn).setCellRenderer(new OcrIconCellRenderer()); + } break; default: } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index 98ab0979a5..c7eb4111bf 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -105,6 +105,7 @@ import org.sleuthkit.autopsy.ingest.IngestModuleError; import org.sleuthkit.autopsy.ingest.IngestStream; import org.sleuthkit.autopsy.keywordsearch.KeywordSearchModuleException; import org.sleuthkit.autopsy.keywordsearch.Server; +import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.SleuthkitCase; @@ -144,7 +145,8 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen ControlEventType.SHUTDOWN.toString(), ControlEventType.GENERATE_THREAD_DUMP_REQUEST.toString(), Event.CANCEL_JOB.toString(), - Event.REPROCESS_JOB.toString()})); + Event.REPROCESS_JOB.toString(), + Event.OCR_STATE_CHANGE.toString()})); private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED); private static final long JOB_STATUS_EVENT_INTERVAL_SECONDS = 10; private static final String JOB_STATUS_PUBLISHING_THREAD_NAME = "AIM-job-status-event-publisher-%d"; @@ -308,6 +310,8 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen handleRemoteJobCancelEvent((AutoIngestJobCancelEvent) event); } else if (event instanceof AutoIngestJobReprocessEvent) { handleRemoteJobReprocessEvent((AutoIngestJobReprocessEvent) event); + } else if (event instanceof AutoIngestOcrStateChangeEvent) { + handleRemoteOcrEvent((AutoIngestOcrStateChangeEvent) event); } } } @@ -466,10 +470,42 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen String hostName = event.getNodeName(); hostNamesToLastMsgTime.put(hostName, Instant.now()); + // currently the only way to the get latest ZK manifest node contents is to do an input directory scan scanInputDirsNow(); setChanged(); notifyObservers(Event.CASE_PRIORITIZED); } + + /** + * Processes a case OCR enabled/disabled event from another node. + * + * @param event OCR enabled/disabled event from another auto ingest node. + */ + private void handleRemoteOcrEvent(AutoIngestOcrStateChangeEvent event) { + switch (event.getEventType()) { + case OCR_ENABLED: + sysLogger.log(Level.INFO, "Received OCR enabled event for case {0} from user {1} on machine {2}", + new Object[]{event.getCaseName(), event.getUserName(), event.getNodeName()}); + break; + case OCR_DISABLED: + sysLogger.log(Level.INFO, "Received OCR disabled event for case {0} from user {1} on machine {2}", + new Object[]{event.getCaseName(), event.getUserName(), event.getNodeName()}); + break; + default: + sysLogger.log(Level.WARNING, "Received invalid OCR enabled/disabled event from user {0} on machine {1}", + new Object[]{event.getUserName(), event.getNodeName()}); + break; + } + + String hostName = event.getNodeName(); + hostNamesToLastMsgTime.put(hostName, Instant.now()); + + // currently the only way to the get latest ZK manifest node contents is to do an input directory scan + scanInputDirsNow(); + + setChanged(); + notifyObservers(Event.OCR_STATE_CHANGE); + } /** * Processes a case deletion event from another node by triggering an @@ -2057,10 +2093,11 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen } iterator.remove(); - currentJob = job; + // create a new job object based on latest ZK node data (i.e. instead of re-using potentially stale local pending AutoIngestJob object). + currentJob = new AutoIngestJob(nodeData); break; - } catch (AutoIngestJobNodeData.InvalidDataException ex) { + } catch (AutoIngestJobNodeData.InvalidDataException | AutoIngestJobException ex) { sysLogger.log(Level.WARNING, String.format("Unable to use node data for %s", manifestPath), ex); } } @@ -2215,21 +2252,20 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen * auto ingest job. */ private void attemptJob() throws CoordinationServiceException, SharedConfigurationException, ServicesMonitorException, DatabaseServerDownException, KeywordSearchServerDownException, CaseManagementException, AnalysisStartupException, FileExportException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException, IOException, JobMetricsCollectionException { - updateConfiguration(); - if (currentJob.isCanceled() || jobProcessingTaskFuture.isCancelled()) { - return; - } verifyRequiredSevicesAreRunning(); if (currentJob.isCanceled() || jobProcessingTaskFuture.isCancelled()) { return; } Case caseForJob = openCase(); try { + if (currentJob.isCanceled() || jobProcessingTaskFuture.isCancelled()) { + return; + } + updateConfiguration(); if (currentJob.isCanceled() || jobProcessingTaskFuture.isCancelled()) { return; } runIngestForJob(caseForJob); - } finally { try { Case.closeCurrentCase(); @@ -2242,7 +2278,8 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen /** * Updates the ingest system settings by downloading the latest version - * of the settings if using shared configuration. + * of the settings if using shared configuration. Also updates the OCR + * setting. * * @throws SharedConfigurationException if there is an error downloading * shared configuration. @@ -2258,6 +2295,15 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen currentJob.setProcessingStage(AutoIngestJob.Stage.UPDATING_SHARED_CONFIG, Date.from(Instant.now())); new SharedConfiguration().downloadConfiguration(); } + + // update the OCR enabled/disabled setting + if (currentJob.getOcrEnabled()) { + sysLogger.log(Level.INFO, "Enabling OCR for job {0}", currentJob.getManifest().getFilePath()); + } else { + sysLogger.log(Level.INFO, "Disabling OCR for job {0}", currentJob.getManifest().getFilePath()); + } + KeywordSearchService kwsService = Lookup.getDefault().lookup(KeywordSearchService.class); + kwsService.changeOcrState(currentJob.getOcrEnabled()); } /** @@ -3151,7 +3197,8 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen REPORT_STATE, CANCEL_JOB, REPROCESS_JOB, - GENERATE_THREAD_DUMP_RESPONSE + GENERATE_THREAD_DUMP_RESPONSE, + OCR_STATE_CHANGE } /** diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java index fbca3f50ee..0022cf6609 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java @@ -84,7 +84,8 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen AutoIngestManager.Event.SHUTTING_DOWN.toString(), AutoIngestManager.Event.SHUTDOWN.toString(), AutoIngestManager.Event.RESUMED.toString(), - AutoIngestManager.Event.GENERATE_THREAD_DUMP_RESPONSE.toString()})); + AutoIngestManager.Event.GENERATE_THREAD_DUMP_RESPONSE.toString(), + AutoIngestManager.Event.OCR_STATE_CHANGE.toString()})); private final AutopsyEventPublisher eventPublisher; private CoordinationService coordinationService; private final ScheduledThreadPoolExecutor coordSvcQueryExecutor; @@ -166,6 +167,8 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen handleAutoIngestNodeStateEvent((AutoIngestNodeStateEvent) event); } else if (event instanceof ThreadDumpResponseEvent) { handleRemoteThreadDumpResponseEvent((ThreadDumpResponseEvent) event); + } else if (event instanceof AutoIngestOcrStateChangeEvent) { + handleOcrStateChangeEvent((AutoIngestOcrStateChangeEvent) event); } } @@ -228,6 +231,15 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen } } + /** + * Handles an OCR state change event. + * + * @param event OCR state change event. + */ + private void handleOcrStateChangeEvent(AutoIngestOcrStateChangeEvent event) { + coordSvcQueryExecutor.submit(new StateRefreshTask()); + } + /** * Handles an auto ingest job/case prioritization event. * @@ -427,6 +439,51 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen return new JobsSnapshot(); } } + + /** + * Enables OCR for all pending ingest jobs for a specified case. + * + * @param caseName The name of the case to enable OCR. + * + * @throws AutoIngestMonitorException If there is an error enabling OCR for the jobs for the case. + * + */ + void changeOcrStateForCase(final String caseName, final boolean ocrState) throws AutoIngestMonitorException { + List jobsToPrioritize = new ArrayList<>(); + synchronized (jobsLock) { + for (AutoIngestJob pendingJob : getPendingJobs()) { + if (pendingJob.getManifest().getCaseName().equals(caseName)) { + jobsToPrioritize.add(pendingJob); + } + } + if (!jobsToPrioritize.isEmpty()) { + for (AutoIngestJob job : jobsToPrioritize) { + String manifestNodePath = job.getManifest().getFilePath().toString(); + try { + AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestNodePath)); + nodeData.setOcrEnabled(ocrState); + coordinationService.setNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestNodePath, nodeData.toArray()); + } catch (AutoIngestJobNodeData.InvalidDataException | CoordinationServiceException | InterruptedException ex) { + throw new AutoIngestMonitorException("Error enabling OCR for job " + job.toString(), ex); + } + job.setOcrEnabled(ocrState); + + /** + * Update job object in pending jobs queue + */ + jobsSnapshot.addOrReplacePendingJob(job); + } + + /* + * Publish the OCR enabled event. + */ + new Thread(() -> { + eventPublisher.publishRemotely(new AutoIngestOcrStateChangeEvent(LOCAL_HOST_NAME, caseName, + AutoIngestManager.getSystemUserNameProperty(), ocrState)); + }).start(); + } + } + } /** * Removes the priority (set to zero) of all pending ingest jobs for a diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestNodeRefreshEvents.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestNodeRefreshEvents.java index 338bce31c7..be7cc2408f 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestNodeRefreshEvents.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestNodeRefreshEvents.java @@ -69,7 +69,7 @@ class AutoIngestNodeRefreshEvents { private final String caseName; /** - * Contructs a RefreshCaseEvent + * Constructs a RefreshCaseEvent * * @param monitor The monitor that will provide access to the current state of the jobs lists. * @param name The name of the case whose nodes should be refreshed. diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestOcrStateChangeEvent.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestOcrStateChangeEvent.java new file mode 100755 index 0000000000..682ad711eb --- /dev/null +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestOcrStateChangeEvent.java @@ -0,0 +1,99 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 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.experimental.autoingest; + +import java.io.Serializable; +import org.sleuthkit.autopsy.events.AutopsyEvent; + +/** + * Event published when an automated ingest manager enables or disables OCR on a case. + */ +public final class AutoIngestOcrStateChangeEvent extends AutopsyEvent implements Serializable { + + /** + * Possible event types + */ + enum EventType { + OCR_ENABLED, + OCR_DISABLED + } + + private static final long serialVersionUID = 1L; + private final String caseName; + private final String nodeName; + private final String userName; + private final EventType eventType; + + /** + * Constructs an event published when an automated ingest manager + * enables or disables OCR on a case. + * + * @param caseName The name of the case. + * @param nodeName The host name of the node that enabled/disabled OCR. + * @param userName The logged in user + * @param ocrState Flag whether OCR is enabled/disabled + */ + public AutoIngestOcrStateChangeEvent(String nodeName, String caseName, String userName, boolean ocrState) { + super(AutoIngestManager.Event.OCR_STATE_CHANGE.toString(), null, null); + this.caseName = caseName; + this.nodeName = nodeName; + this.userName = userName; + if (ocrState == true) { + this.eventType = EventType.OCR_ENABLED; + } else { + this.eventType = EventType.OCR_DISABLED; + } + } + + /** + * Gets the name of the prioritized case. + * + * @return The case name. + */ + public String getCaseName() { + return caseName; + } + + /** + * Gets the host name of the node that prioritized the case. + * + * @return The host name of the node. + */ + public String getNodeName() { + return nodeName; + } + + /** + * Gets the user logged in to the node that prioritized the case. + * + * @return The user name + */ + String getUserName() { + return userName; + } + + /** + * Gets the type of prioritization + * + * @return The type + */ + EventType getEventType() { + return eventType; + } +} diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED index 4447162072..2a1e361537 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED @@ -10,6 +10,10 @@ AinStatusNode.status.title=Status AinStatusNode.status.unknown=Unknown AutoIngestAdminActions.cancelJobAction.title=Cancel Job AutoIngestAdminActions.cancelModuleAction.title=Cancel Module +AutoIngestAdminActions.disableOCR.error=Failed to disable OCR for case "%s". +AutoIngestAdminActions.disableOCR.title=Disable OCR For This Case +AutoIngestAdminActions.enableOCR.error=Failed to enable OCR for case "%s". +AutoIngestAdminActions.enableOCR.title=Enable OCR For This Case AutoIngestAdminActions.getThreadDump.title=Generate Thread Dump AutoIngestAdminActions.pause.title=Pause Node AutoIngestAdminActions.progressDialogAction.title=Ingest Progress @@ -71,6 +75,7 @@ AutoIngestControlPanel.JobsTableModel.ColumnHeader.HostName=Host Name AutoIngestControlPanel.JobsTableModel.ColumnHeader.ImageFolder=Data Source AutoIngestControlPanel.JobsTableModel.ColumnHeader.LocalJob=\ Local Job? AutoIngestControlPanel.JobsTableModel.ColumnHeader.ManifestFilePath=\ Manifest File Path +AutoIngestControlPanel.JobsTableModel.ColumnHeader.OCR=OCR AutoIngestControlPanel.JobsTableModel.ColumnHeader.Priority=Prioritized AutoIngestControlPanel.JobsTableModel.ColumnHeader.Stage=Stage AutoIngestControlPanel.JobsTableModel.ColumnHeader.StageTime=Time in Stage @@ -130,6 +135,7 @@ AutoIngestJobsNode.dataSource.text=Data Source AutoIngestJobsNode.hostName.text=Host Name AutoIngestJobsNode.jobCompleted.text=Job Completed AutoIngestJobsNode.jobCreated.text=Job Created +AutoIngestJobsNode.ocr.text=OCR AutoIngestJobsNode.prioritized.false=No AutoIngestJobsNode.prioritized.true=Yes AutoIngestJobsNode.priority.text=Prioritized @@ -206,9 +212,7 @@ DeleteCaseTask.progress.parsingManifest=Parsing manifest file {0}... DeleteCaseTask.progress.releasingManifestLock=Releasing lock on the manifest file {0}... DeleteCaseTask.progress.startMessage=Starting deletion... DeleteOrphanCaseNodesAction.progressDisplayName=Cleanup Case Znodes -# {0} - item count DeleteOrphanCaseNodesDialog.additionalInit.lblNodeCount.text=Znodes found: {0} -# {0} - item count DeleteOrphanCaseNodesDialog.additionalInit.znodesTextArea.countMessage=ZNODES FOUND: {0} DeleteOrphanCaseNodesTask.progress.connectingToCoordSvc=Connecting to the coordination service # {0} - node path @@ -224,6 +228,8 @@ DeleteOrphanManifestNodesTask.progress.gettingManifestNodes=Querying the coordin DeleteOrphanManifestNodesTask.progress.lookingForOrphanedManifestFileZnodes=Looking for orphaned manifest file znodes DeleteOrphanManifestNodesTask.progress.startMessage=Starting orphaned manifest file znode cleanup HINT_CasesDashboardTopComponent=This is an adminstrative dashboard for multi-user cases +OcrIconCellRenderer.disabled.tooltiptext=This job does not have OCR enabled. +OcrIconCellRenderer.enabled.tooltiptext=This job has OCR enabled. OpenAutoIngestLogAction.deletedLogErrorMsg=The case auto ingest log has been deleted. OpenAutoIngestLogAction.logOpenFailedErrorMsg=Failed to open case auto ingest log. See application log for details. OpenAutoIngestLogAction.menuItemText=Open Auto Ingest Log File @@ -333,7 +339,7 @@ PrioritizationAction.deprioritizeCaseAction.error=Failed to deprioritize case "% PrioritizationAction.deprioritizeCaseAction.title=Deprioritize Case PrioritizationAction.deprioritizeJobAction.error=Failed to deprioritize job "%s". PrioritizationAction.deprioritizeJobAction.title=Deprioritize Job -PrioritizationAction.prioritizeCaseAction.error==Failed to prioritize case "%s". +PrioritizationAction.prioritizeCaseAction.error=Failed to prioritize case "%s". PrioritizationAction.prioritizeCaseAction.title=Prioritize Case PrioritizationAction.prioritizeJobAction.error=Failed to prioritize job "%s". PrioritizationAction.prioritizeJobAction.title=Prioritize Job diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/OcrIconCellRenderer.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/OcrIconCellRenderer.java new file mode 100755 index 0000000000..e90754adf8 --- /dev/null +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/OcrIconCellRenderer.java @@ -0,0 +1,72 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 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.experimental.autoingest; + +import java.awt.Component; +import java.lang.reflect.InvocationTargetException; +import javax.swing.ImageIcon; +import javax.swing.JTable; +import static javax.swing.SwingConstants.CENTER; +import org.openide.nodes.Node; +import org.openide.util.ImageUtilities; +import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.guiutils.GrayableCellRenderer; +import org.sleuthkit.autopsy.datamodel.NodeProperty; + +/** + * A JTable and Outline view cell renderer that represents whether OCR is enabled for the job. + */ +class OcrIconCellRenderer extends GrayableCellRenderer { + + @Messages({ + "OcrIconCellRenderer.enabled.tooltiptext=This job has OCR enabled.", + "OcrIconCellRenderer.disabled.tooltiptext=This job does not have OCR enabled." + }) + private static final long serialVersionUID = 1L; + static final ImageIcon checkedIcon = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/experimental/images/tick.png", false)); + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + setHorizontalAlignment(CENTER); + Object switchValue = null; + if ((value instanceof NodeProperty)) { + //The Outline view has properties in the cell, the value contained in the property is what we want + try { + switchValue = ((Node.Property) value).getValue(); + } catch (IllegalAccessException | InvocationTargetException ignored) { + //Unable to get the value from the NodeProperty no Icon will be displayed + } + } else { + //JTables contain the value we want directly in the cell + switchValue = value; + } + if (switchValue instanceof Boolean && (boolean) switchValue == true) { + setIcon(checkedIcon); + setToolTipText(org.openide.util.NbBundle.getMessage(OcrIconCellRenderer.class, "OcrIconCellRenderer.enabled.tooltiptext")); + } else { + setIcon(null); + if (switchValue instanceof Boolean) { + setToolTipText(org.openide.util.NbBundle.getMessage(OcrIconCellRenderer.class, "OcrIconCellRenderer.disabled.tooltiptext")); + } + } + grayCellIfTableNotEnabled(table, isSelected); + + return this; + } +} diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PrioritizationAction.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PrioritizationAction.java index 006dc3e580..97ad2cee63 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PrioritizationAction.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PrioritizationAction.java @@ -193,7 +193,7 @@ abstract class PrioritizationAction extends AbstractAction { * AutoIngestJob is a part of. */ @Messages({"PrioritizationAction.prioritizeCaseAction.title=Prioritize Case", - "PrioritizationAction.prioritizeCaseAction.error==Failed to prioritize case \"%s\"."}) + "PrioritizationAction.prioritizeCaseAction.error=Failed to prioritize case \"%s\"."}) static final class PrioritizeCaseAction extends PrioritizationAction { private static final long serialVersionUID = 1L; diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/volatilityDSP/Bundle_ja.properties b/Experimental/src/org/sleuthkit/autopsy/experimental/volatilityDSP/Bundle_ja.properties new file mode 100644 index 0000000000..ac4a0e8259 --- /dev/null +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/volatilityDSP/Bundle_ja.properties @@ -0,0 +1,3 @@ +#Mon Jun 14 12:23:19 UTC 2021 +MemoryDSInputPanel.deselectAllButton.text=\u5168\u9078\u629e\u3092\u30af\u30ea\u30a2 +MemoryDSInputPanel.selectAllButton.text=\u3059\u3079\u3066\u9078\u629e diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle_ja.properties b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle_ja.properties index d43448a582..306f4bf3b4 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle_ja.properties +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle_ja.properties @@ -1,4 +1,4 @@ -#Fri Feb 12 16:56:29 UTC 2021 +#Mon Jun 14 12:23:19 UTC 2021 AbstractFileStringContentStream.getSize.exception.msg=\u6587\u5b57\u5217\u5168\u4f53\u304c\u5909\u63db\u3055\u308c\u308b\u307e\u3067\u3001\u5909\u63db\u3055\u308c\u305f\u6587\u5b57\u5217\u306e\u6587\u5b57\u6570\u306f\u308f\u304b\u308a\u307e\u305b\u3093 AbstractFileStringContentStream.getSrcInfo.text=\u30d5\u30a1\u30a4\u30eb\:{0} AbstractFileTikaTextExtract.index.exception.tikaParse.msg=\u4f8b\u5916\: \u6b21\u306e\u30d5\u30a1\u30a4\u30eb\u306eTika\u89e3\u6790\u30bf\u30b9\u30af\u5b9f\u884c\u6642\u306e\u4e88\u671f\u305b\u306c\u4f8b\u5916\: {0}\u3001{1} @@ -47,6 +47,17 @@ DropdownSingleTermSearchPanel.jSaveSearchResults.toolTipText=\u30ad\u30fc\u30ef\ DropdownSingleTermSearchPanel.selected=\u30a2\u30c9\u30db\u30c3\u30af\u691c\u7d22\u30bd\u30fc\u30b9\u30d5\u30a3\u30eb\u30bf\u30fc\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u307e\u3059 DropdownSingleTermSearchPanel.warning.text=\u5883\u754c\u6587\u5b57 ^ \u3068 $ \u304c\u5358\u8a9e\u9818\u57df\u3068\u4e00\u81f4\u3057\u307e\u305b\u3093\u3002[ \\.,] \u306a\u3069\u306e\u660e\u793a\u7684\u306a\u5883\u754c\u6587\u5b57\u30ea\u30b9\u30c8\u3068\u306e\u7f6e\u63db\u3092\n\u691c\u8a0e\u3057\u3066\u304f\u3060\u3055\u3044 DropdownSingleTermSearchPanel.warning.title=\u8b66\u544a +ExtractAllTermsReport.description.text=\u73fe\u5728\u306e\u30b1\u30fc\u30b9\u304b\u3089\u3059\u3079\u3066\u306e\u30e6\u30cb\u30fc\u30af\u306e\u5358\u8a9e\u3092\u62bd\u51fa\u3057\u307e\u3059\u3002 \u6ce8\uff1a\u62bd\u51fa\u3055\u308c\u305f\u5358\u8a9e\u306f\u5c0f\u6587\u5b57\u3067\u3059\u3002 +ExtractAllTermsReport.error.noOpenCase=\u73fe\u5728\u958b\u3044\u3066\u3044\u308b\u30b1\u30fc\u30b9\u306f\u3042\u308a\u307e\u305b\u3093\u3002 +ExtractAllTermsReport.export.error=\u30e6\u30cb\u30fc\u30af\u306e\u5358\u8a9e\u306e\u62bd\u51fa\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +ExtractAllTermsReport.exportComplete=\u30e6\u30cb\u30fc\u30af\u306a\u5358\u8a9e\u62bd\u51fa\u5b8c\u4e86 +ExtractAllTermsReport.getName.text=\u30e6\u30cb\u30fc\u30af\u306a\u5358\u8a9e\u3092\u62bd\u51fa\u3059\u308b +ExtractAllTermsReport.numberExtractedTerms={0}\u7528\u8a9e.\u304c\u62bd\u51fa\u3055\u308c\u307e\u3057\u305f.. +ExtractAllTermsReport.search.ingestInProgressBody=\u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22\u53d6\u8fbc\u307f\u306f\u73fe\u5728\u5b9f\u884c\u4e2d\u3067\u3059\u3002
\u5168\u3066\u306e\u30d5\u30a1\u30a4\u30eb\u304c\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306b\u767b\u9332\u3055\u308c\u3066\u307e\u305b\u3093\u3001\u30e6\u30cb\u30fc\u30af\u306a\u5358\u8a9e\u3092\u62bd\u51fa\u3059\u308b\u3068\u4e0d\u5b8c\u5168\u306a\u7d50\u679c\u306b\u306a\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002
\u305d\u308c\u3067\u3082\u30e6\u30cb\u30fc\u30af\u306a\u5358\u8a9e\u306e\u62bd\u51fa\u3092\u7d9a\u884c\u3057\u307e\u3059\u304b\uff1f +ExtractAllTermsReport.search.noFilesInIdxMsg=\u307e\u3060\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306b\u767b\u9332\u3055\u308c\u3066\u3044\u308b\u30d5\u30a1\u30a4\u30eb\u306f\u3042\u308a\u307e\u305b\u3093\u3002 \u3042\u3068\u3067\u3082\u3046\u4e00\u5ea6\u8a66\u3057\u3066\u304f\u3060\u3055\u3044\u3002 \u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306f{0}\u5206\u3054\u3068\u306b\u66f4\u65b0\u3055\u308c\u307e\u3059\u3002 +ExtractAllTermsReport.search.noFilesInIdxMsg2=\u307e\u3060\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306b\u767b\u9332\u3055\u308c\u3066\u3044\u308b\u30d5\u30a1\u30a4\u30eb\u306f\u3042\u308a\u307e\u305b\u3093\u3002 \u3042\u3068\u3067\u3082\u3046\u4e00\u5ea6\u8a66\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +ExtractAllTermsReport.search.searchIngestInProgressTitle=\u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22\u306e\u53d6\u8fbc\u307f\u304c\u9032\u884c\u4e2d +ExtractAllTermsReport.startExport=\u30e6\u30cb\u30fc\u30af\u306a\u5358\u8a9e\u62bd\u51fa\u306e\u958b\u59cb ExtractedContentPanel.SetMarkup.progress.loading={0} \u306e\u30c6\u30ad\u30b9\u30c8\u3092\u8aad\u307f\u8fbc\u3093\u3067\u3044\u307e\u3059 ExtractedContentPanel.copyMenuItem.text=\u30b3\u30d4\u30fc ExtractedContentPanel.hitButtonsLabel.text=\u4e00\u81f4\u3059\u308b\u7d50\u679c @@ -333,11 +344,12 @@ Server.deleteCore.exception.msg=Solr\u30b3\u30ec\u30af\u30b7\u30e7\u30f3{0}\u306 Server.exceptionMessage.unableToBackupCollection=Solr\u30b3\u30ec\u30af\u30b7\u30e7\u30f3\u3092\u30d0\u30c3\u30af\u30a2\u30c3\u30d7\u3067\u304d\u307e\u305b\u3093 Server.exceptionMessage.unableToCreateCollection=Solr\u30b3\u30ec\u30af\u30b7\u30e7\u30f3\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093 Server.exceptionMessage.unableToRestoreCollection=Solr\u30b3\u30ec\u30af\u30b7\u30e7\u30f3\u3092\u5fa9\u5143\u3067\u304d\u307e\u305b\u3093 +Server.getAllTerms.error=\u5168\u3066\u306e\u30e6\u30cb\u30fc\u30af\u306aSolr\u7528\u8a9e\u306e\u62bd\u51fa\u306b\u5931\u6557\u3057\u307e\u3057\u305f\uff1a Server.isRunning.exception.errCheckSolrRunning.msg=Solr\u30b5\u30fc\u30d0\u30fc\u304c\u5b9f\u884c\u4e2d\u304b\u3069\u3046\u304b\u3092\u78ba\u8a8d\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f Server.isRunning.exception.errCheckSolrRunning.msg2=Solr\u30b5\u30fc\u30d0\u30fc\u304c\u5b9f\u884c\u4e2d\u304b\u3069\u3046\u304b\u3092\u78ba\u8a8d\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f Server.openCore.exception.alreadyOpen.msg=\u958b\u3044\u3066\u3044\u308bSolr\u306e\u30b3\u30a2\u304c\u3059\u3067\u306b\u3042\u308a\u307e\u3059\u3002\u6700\u521d\u306b\u30b3\u30a2\u3092\u660e\u793a\u7684\u306b\u9589\u3058\u3066\u304f\u3060\u3055\u3044\u3002 Server.openCore.exception.cantOpen.msg=\u7d22\u5f15\u3092\u4f5c\u6210\u307e\u305f\u306f\u958b\u3051\u307e\u305b\u3093\u3067\u3057\u305f -Server.openCore.exception.msg=\u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22\u30b5\u30fc\u30d3\u30b9\u306f\u307e\u3060\u5b9f\u884c\u3057\u3066\u3044\u307e\u305b\u3093 +Server.openCore.exception.msg=\u30ed\u30fc\u30ab\u30eb\u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22\u30b5\u30fc\u30d3\u30b9\u306f\u307e\u3060\u5b9f\u884c\u3055\u308c\u3066\u3044\u307e\u305b\u3093 Server.openCore.exception.noIndexDir.msg=\u7d22\u5f15\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fc\u3092\u4f5c\u6210\u3067\u304d\u306a\u304b\u3063\u305f\u304b\u3001\u898b\u3064\u304b\u308a\u307e\u305b\u3093 Server.query.exception.msg=\u6b21\u306e\u30af\u30a8\u30ea\u306e\u5b9f\u884c\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\: {0} Server.query2.exception.msg=\u6b21\u306e\u30af\u30a8\u30ea\u306e\u5b9f\u884c\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\: {0} @@ -360,10 +372,12 @@ SolrSearch.checkingForLatestIndex.msg=\u6700\u65b0\u306eSolr\u3068\u30b9\u30ad\u SolrSearch.complete.msg=\u30c6\u30ad\u30b9\u30c8\u7d22\u5f15\u304c\u6b63\u5e38\u306b\u958b\u304d\u307e\u3057\u305f SolrSearch.creatingNewIndex.msg=\u65b0\u898f\u30c6\u30ad\u30b9\u30c8\u7d22\u5f15\u3092\u751f\u6210\u4e2d\u3067\u3059 SolrSearch.findingIndexes.msg=\u65e2\u5b58\u306e\u30c6\u30ad\u30b9\u30c8\u7d22\u5f15\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fc\u3092\u691c\u7d22\u4e2d\u3067\u3059 +SolrSearch.futureIndexVersion.msg=\u30b1\u30fc\u30b9\u306e\u30c6\u30ad\u30b9\u30c8\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306fSolr {0}\u7528\u3067\u3059\u3002 \u3053\u306e\u30d0\u30fc\u30b8\u30e7\u30f3\u306eAutopsy\u306f\u3001Solr {1}\u3068\u4e92\u63db\u6027\u304c\u3042\u308a\u307e\u3059\u3002 SolrSearch.indentifyingIndex.msg=\u4f7f\u7528\u3059\u308b\u30c6\u30ad\u30b9\u30c8\u7d22\u5f15\u3092\u7279\u5b9a\u4e2d\u3067\u3059 SolrSearch.lookingForMetadata.msg=\u30c6\u30ad\u30b9\u30c8\u7d22\u5f15\u306e\u30e1\u30bf\u30c7\u30fc\u30bf\u30d5\u30a1\u30a4\u30eb\u3092\u691c\u7d22\u4e2d\u3067\u3059 SolrSearch.openCore.msg=\u30c6\u30ad\u30b9\u30c8\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u3092\u958b\u304d\u307e\u3059\u3002 \u3053\u308c\u306b\u306f\u6570\u5206\u304b\u304b\u308b\u5834\u5408\u304c\u3042\u308a\u307e\u3059\u3002 SolrSearch.readingIndexes.msg=\u30c6\u30ad\u30b9\u30c8\u7d22\u5f15\u306e\u30e1\u30bf\u30c7\u30fc\u30bf\u30d5\u30a1\u30a4\u30eb\u3092\u8aad\u307f\u8fbc\u307f\u4e2d\u3067\u3059 +SolrSearch.unableToFindIndex.msg=\u30b1\u30fc\u30b9\u306b\u4f7f\u7528\u3067\u304d\u308b\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093 SolrSearchService.ServiceName=Solr\u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22\u30b5\u30fc\u30d3\u30b9 SolrSearchService.exceptionMessage.failedToDeleteIndexFiles={0} \u306e\u30c6\u30ad\u30b9\u30c8\u7d22\u5f15\u30d5\u30a1\u30a4\u30eb\u3092\u524a\u9664\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f SolrSearchService.exceptionMessage.noCurrentSolrCore=IndexMetadata\u306b\u306f\u73fe\u5728\u306eSolr\u306e\u30b3\u30a2\u304c\u542b\u307e\u308c\u3066\u3044\u306a\u304b\u3063\u305f\u305f\u3081\u3001\u30b1\u30fc\u30b9\u3092\u524a\u9664\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentPanel.java index 8ff9c0fdcc..c64cee2565 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentPanel.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2020 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,10 +29,10 @@ import java.util.List; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.logging.Level; -import javax.swing.JLabel; import javax.swing.SizeRequirements; import javax.swing.SwingUtilities; import javax.swing.SwingWorker; +import javax.swing.UIManager; import javax.swing.text.Element; import javax.swing.text.View; import javax.swing.text.ViewFactory; @@ -59,7 +59,7 @@ class ExtractedContentPanel extends javax.swing.JPanel implements ResizableTextP private static final Logger logger = Logger.getLogger(ExtractedContentPanel.class.getName()); // set font as close as possible to default - private static final Font DEFAULT_FONT = new JLabel().getFont(); + private static final Font DEFAULT_FONT = UIManager.getDefaults().getFont("Label.font"); private static final long serialVersionUID = 1L; private String contentName; @@ -72,7 +72,6 @@ class ExtractedContentPanel extends javax.swing.JPanel implements ResizableTextP ExtractedContentPanel() { initComponents(); additionalInit(); - setSources("", new ArrayList<>()); hitPreviousButton.setEnabled(false); hitNextButton.setEnabled(false); @@ -135,7 +134,7 @@ class ExtractedContentPanel extends javax.swing.JPanel implements ResizableTextP }; } }; - // get the style sheet for editing font size + // set new style sheet to clear default styles styleSheet = editorKit.getStyleSheet(); sourceComboBox.addItemListener(itemEvent -> { @@ -144,6 +143,7 @@ class ExtractedContentPanel extends javax.swing.JPanel implements ResizableTextP } }); extractedTextPane.setComponentPopupMenu(rightClickMenu); + copyMenuItem.addActionListener(actionEvent -> extractedTextPane.copy()); selectAllMenuItem.addActionListener(actionEvent -> extractedTextPane.selectAll()); @@ -156,11 +156,16 @@ class ExtractedContentPanel extends javax.swing.JPanel implements ResizableTextP if (zoomPanel instanceof TextZoomPanel) ((TextZoomPanel) this.zoomPanel).resetSize(); }); + + setSources("", new ArrayList<>()); } private void setStyleSheetSize(StyleSheet styleSheet, int size) { - styleSheet.addRule("body {font-family:\"" + DEFAULT_FONT.getFamily() + "\"; font-size:" + size + "pt; } "); + styleSheet.addRule( + "body { font-family:\"" + DEFAULT_FONT.getFamily() + "\"; font-size:" + size + "pt; } " + + "pre { font-family:\"" + DEFAULT_FONT.getFamily() + "\"; font-size:" + size + "pt; } " + ); } @@ -499,6 +504,8 @@ class ExtractedContentPanel extends javax.swing.JPanel implements ResizableTextP extractedTextPane.applyComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT); } + // refresh style + setStyleSheetSize(styleSheet, curSize); extractedTextPane.setText(safeText); extractedTextPane.setCaretPosition(0); } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java index 218be24de8..09460a0788 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java @@ -462,4 +462,17 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService { } } + /** + * A flag to enable or disable OCR on all future text indexing. Also sets the + * the "Limited OCR" functionality accordingly. + * + * @param state Boolean flag to enable/disable OCR. Set to True to enable + * OCR, or False to disable it. + */ + @Override + public void changeOcrState(boolean state) { + KeywordSearchSettings.setOcrOption(state); + KeywordSearchSettings.setLimitedOcrOption(state); + } + } diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle_ja.properties b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle_ja.properties index e1ea4fb368..ab01f5b7cc 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle_ja.properties +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle_ja.properties @@ -1,4 +1,4 @@ -#Fri Feb 12 16:56:29 UTC 2021 +#Mon Jun 14 12:23:19 UTC 2021 Chrome.getBookmark.errMsg.errAnalyzeFile={0}\:\u30d5\u30a1\u30a4\u30eb\:{1}\u3092\u89e3\u6790\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f Chrome.getBookmark.errMsg.errAnalyzingFile={0}\:\u30d5\u30a1\u30a4\u30eb\:{1}\u3092\u89e3\u6790\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f Chrome.getBookmark.errMsg.errAnalyzingFile3={0}\:\u30d5\u30a1\u30a4\u30eb\:{1}\u3092\u89e3\u6790\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f @@ -80,7 +80,7 @@ Firefox.moduleName=FireFox Firefox.parentModuleName=\u6700\u8fd1\u306e\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3 Firefox.parentModuleName.noSpace=\u6700\u8fd1\u306e\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3 OpenIDE-Module-Display-Category=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb -OpenIDE-Module-Long-Description=\u6700\u8fd1\u306e\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3002\n\n\u3053\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u306f\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u4e2d\u306e\u30c7\u30a3\u30b9\u30af\u30a4\u30e1\u30fc\u30b8\u304b\u3089\u6709\u7528\u306a\u6700\u8fd1\u306e\u30e6\u30fc\u30b6\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3\u3092\u62bd\u51fa\u3057\u307e\u3059\u3002\u4f8b\u3048\u3070\uff1a\n\n-\u6700\u8fd1\u958b\u3044\u305f\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\u3001\n-\u30a6\u30a7\u30d6\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3\uff08\u8a2a\u308c\u305f\u30b5\u30a4\u30c8\u3001\u4fdd\u5b58\u3055\u308c\u305fCookie\u3001\u30d6\u30c3\u30af\u30de\u30fc\u30af\u3055\u308c\u305f\u30b5\u30a4\u30c8\u3001\u30b5\u30fc\u30c1\u30a8\u30f3\u30b8\u30f3\u30af\u30a8\u30ea\u3001\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb\uff09\u3001\n-\u6700\u8fd1\u63a5\u7d9a\u3057\u305f\u30c7\u30d0\u30a4\u30b9\u3001\n-\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3055\u308c\u305f\u30d7\u30ed\u30b0\u30e9\u30e0\u3002\n\n\u3053\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u306f\u73fe\u5728Windows\u306e\u30c7\u30a3\u30b9\u30af\u30a4\u30e1\u30fc\u30b8\u3057\u304b\u30b5\u30dd\u30fc\u30c8\u3057\u3066\u3044\u307e\u305b\u3093\u3002\n\u30d7\u30e9\u30b0\u30a4\u30f3\u306fWindows\u7248\u306eAutopsy\u3092\u5229\u7528\u3059\u308b\u3068\u5168\u3066\u306e\u6a5f\u80fd\u304c\u4f7f\u3048\u307e\u3059\u3002 +OpenIDE-Module-Long-Description=\u6700\u8fd1\u306e\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3\u53d6\u8fbc\u307f\u30e2\u30b8\u30e5\u30fc\u30eb\u3002\n\n\u3053\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u306f\u3001\u53d6\u8fbc\u307e\u308c\u3066\u3044\u308b\u30c7\u30a3\u30b9\u30af\u30a4\u30e1\u30fc\u30b8\u3067\u306e\u6700\u8fd1\u306e\u30e6\u30fc\u30b6\u30fc\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3\u306b\u95a2\u3059\u308b\u6709\u7528\u306a\u60c5\u5831\u3092\u62bd\u51fa\u3057\u307e\u3059\u3002\n\n-\u6700\u8fd1\u958b\u3044\u305f\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\u3001\n-Web\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3\uff08\u30a2\u30af\u30bb\u30b9\u3057\u305f\u30b5\u30a4\u30c8\u3001\u4fdd\u5b58\u3055\u308c\u305fCookie\u3001\u30d6\u30c3\u30af\u30de\u30fc\u30af\u3055\u308c\u305f\u30b5\u30a4\u30c8\u3001\u691c\u7d22\u30a8\u30f3\u30b8\u30f3\u30af\u30a8\u30ea\u3001\u30d5\u30a1\u30a4\u30eb\u306e\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\uff09\u3001\n-\u6700\u8fd1\u63a5\u7d9a\u3055\u308c\u305f\u30c7\u30d0\u30a4\u30b9\u3001\n-\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3055\u308c\u305f\u30d7\u30ed\u30b0\u30e9\u30e0\u3002\n\n\u3053\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u306fWindows\u306e\u307f\u306e\u30c7\u30a3\u30b9\u30af\u30a4\u30e1\u30fc\u30b8\u3092\u30b5\u30dd\u30fc\u30c8\u3057\u3066\u3044\u307e\u3059\u3002\nWindows\u30d0\u30fc\u30b8\u30e7\u30f3\u306eAutopsy\u306b\u30c7\u30d7\u30ed\u30a4\u3059\u308b\u3068\u30d7\u30e9\u30b0\u30a4\u30f3\u306f\u5b8c\u5168\u306b\u6a5f\u80fd\u3057\u307e\u3059\u3002 OpenIDE-Module-Name=\u6700\u8fd1\u306e\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3 OpenIDE-Module-Short-Description=\u6700\u8fd1\u306e\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3\u30d5\u30a1\u30a4\u30f3\u30c0\u30fc\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb Progress_Message_Chrome_AutoFill=Chrome\u81ea\u52d5\u5165\u529b\u30d6\u30e9\u30a6\u30b6{0} diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ChromeCacheExtractor.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ChromeCacheExtractor.java index 9435161a23..f3e073e7f9 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ChromeCacheExtractor.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ChromeCacheExtractor.java @@ -596,8 +596,9 @@ final class ChromeCacheExtractor { if (fileCopyCache.containsKey(fileTableKey)) { return Optional.of(fileCopyCache.get(fileTableKey).getAbstractFile()); } - - List cacheFiles = fileManager.findFiles(dataSource, cacheFileName, cacheFolderName); //NON-NLS + + List cacheFiles = currentCase.getSleuthkitCase().getFileManager().findFilesExactNameExactPath(dataSource, + cacheFileName, cacheFolderName); if (!cacheFiles.isEmpty()) { // Sort the list for consistency. Preference is: // - In correct subfolder and allocated diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chromium.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chromium.java index a3db639b32..371394ff10 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chromium.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chromium.java @@ -633,7 +633,7 @@ class Chromium extends Extract { BlackboardArtifact webDownloadArtifact = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadFile, bbattributes); bbartifacts.add(webDownloadArtifact); String normalizedFullPath = FilenameUtils.normalize(fullPath, true); - for (AbstractFile downloadedFile : fileManager.findFiles(dataSource, FilenameUtils.getName(normalizedFullPath), FilenameUtils.getPath(normalizedFullPath))) { + for (AbstractFile downloadedFile : currentCase.getSleuthkitCase().getFileManager().findFilesExactNameExactPath(dataSource, FilenameUtils.getName(normalizedFullPath), FilenameUtils.getPath(normalizedFullPath))) { bbartifacts.add(createAssociatedArtifact(downloadedFile, webDownloadArtifact)); break; } diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/DataSourceUsageAnalyzer.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/DataSourceUsageAnalyzer.java index bd6b5836d5..0e4fa5ecf1 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/DataSourceUsageAnalyzer.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/DataSourceUsageAnalyzer.java @@ -157,17 +157,13 @@ class DataSourceUsageAnalyzer extends Extract { * does not exist with the given description. * * @param osType - the OS_TYPE to check for - * - * @return true if any specified files exist false if none exist */ private void checkIfOsSpecificVolume(ExtractOs.OS_TYPE osType) throws TskCoreException { - FileManager fileManager = currentCase.getServices().getFileManager(); for (String filePath : osType.getFilePaths()) { - for (AbstractFile file : fileManager.findFiles(dataSource, FilenameUtils.getName(filePath), FilenameUtils.getPath(filePath))) { - if ((file.getParentPath() + file.getName()).equals(filePath)) { - createDataSourceUsageArtifact(osType.getDsUsageLabel()); - return; - } + for (AbstractFile file : currentCase.getSleuthkitCase().getFileManager().findFilesExactNameExactPath(dataSource, + FilenameUtils.getName(filePath), FilenameUtils.getPath(filePath))) { + createDataSourceUsageArtifact(osType.getDsUsageLabel()); + return; } } } diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractOs.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractOs.java index a76c1652dd..6bc00ada63 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractOs.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractOs.java @@ -117,12 +117,10 @@ class ExtractOs extends Extract { * search for */ private AbstractFile getFirstFileFound(List pathsToSearchFor) throws TskCoreException{ - FileManager fileManager = currentCase.getServices().getFileManager(); for (String filePath : pathsToSearchFor) { - for (AbstractFile file : fileManager.findFiles(dataSource, FilenameUtils.getName(filePath), FilenameUtils.getPath(filePath))) { - if ((file.getParentPath() + file.getName()).equals(filePath)) { - return file; - } + List files = currentCase.getSleuthkitCase().getFileManager().findFilesExactNameExactPath(dataSource, FilenameUtils.getName(filePath), FilenameUtils.getPath(filePath)); + if (!files.isEmpty()) { + return files.get(0); } } return null; diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java index cd2eefc4f4..bc5a4de60e 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java @@ -29,7 +29,9 @@ import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; +import java.io.InputStreamReader; import java.io.StringReader; +import java.nio.charset.StandardCharsets; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.logging.Level; @@ -1062,7 +1064,7 @@ class ExtractRegistry extends Extract { File regfile = new File(regFilePath); List newArtifacts = new ArrayList<>(); - try (BufferedReader bufferedReader = new BufferedReader(new FileReader(regfile))) { + try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(regfile), StandardCharsets.UTF_8))) { // Read the file in and create a Document and elements String userInfoSection = "User Information"; String previousLine = null; @@ -1684,18 +1686,13 @@ class ExtractRegistry extends Extract { * @returnv BlackboardArtifact or a null value */ private BlackboardArtifact createAssociatedArtifact(String filePathName, BlackboardArtifact bba) { - org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager(); String fileName = FilenameUtils.getName(filePathName); String filePath = FilenameUtils.getPath(filePathName); List sourceFiles; try { - sourceFiles = fileManager.findFiles(dataSource, fileName, filePath); //NON-NLS + sourceFiles = currentCase.getSleuthkitCase().getFileManager().findFilesExactNameExactPath(dataSource, fileName, filePath); if (!sourceFiles.isEmpty()) { - for (AbstractFile sourceFile : sourceFiles) { - if (sourceFile.getParentPath().endsWith(filePath)) { - return createAssociatedArtifact(sourceFile, bba); - } - } + return createAssociatedArtifact(sourceFiles.get(0), bba); } } catch (TskCoreException ex) { // only catching the error and displaying the message as the file may not exist on the diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractSafari.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractSafari.java index 2bf0351542..429666f8d6 100755 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractSafari.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractSafari.java @@ -647,8 +647,6 @@ final class ExtractSafari extends Extract { Long time = null; Long pathID = null; - FileManager fileManager = getCurrentCase().getServices().getFileManager(); - NSString nsstring = (NSString) entry.get(PLIST_KEY_DOWNLOAD_URL); if (nsstring != null) { url = nsstring.toString(); @@ -669,7 +667,8 @@ final class ExtractSafari extends Extract { bbartifacts.add(webDownloadArtifact); // find the downloaded file and create a TSK_ASSOCIATED_OBJECT for it, associating it with the TSK_WEB_DOWNLOAD artifact. - for (AbstractFile downloadedFile : fileManager.findFiles(dataSource, FilenameUtils.getName(path), FilenameUtils.getPath(path))) { + for (AbstractFile downloadedFile : currentCase.getSleuthkitCase().getFileManager().findFilesExactNameExactPath(dataSource, + FilenameUtils.getName(path), FilenameUtils.getPath(path))) { bbartifacts.add(createAssociatedArtifact(downloadedFile, webDownloadArtifact)); break; } diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Firefox.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Firefox.java index 6dd30ed4cc..87bbb0232d 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Firefox.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Firefox.java @@ -592,7 +592,8 @@ class Firefox extends Extract { bbartifacts.add(webDownloadArtifact); // find the downloaded file and create a TSK_ASSOCIATED_OBJECT for it, associating it with the TSK_WEB_DOWNLOAD artifact. - for (AbstractFile downloadedFile : fileManager.findFiles(dataSource, FilenameUtils.getName(downloadedFilePath), FilenameUtils.getPath(downloadedFilePath))) { + for (AbstractFile downloadedFile : currentCase.getSleuthkitCase().getFileManager().findFilesExactNameExactPath(dataSource, + FilenameUtils.getName(downloadedFilePath), FilenameUtils.getPath(downloadedFilePath))) { bbartifacts.add(createAssociatedArtifact(downloadedFile, webDownloadArtifact)); break; } @@ -727,7 +728,8 @@ class Firefox extends Extract { bbartifacts.add(webDownloadArtifact); // find the downloaded file and create a TSK_ASSOCIATED_OBJECT for it, associating it with the TSK_WEB_DOWNLOAD artifact. - for (AbstractFile downloadedFile : fileManager.findFiles(dataSource, FilenameUtils.getName(downloadedFilePath), FilenameUtils.getPath(downloadedFilePath))) { + for (AbstractFile downloadedFile : currentCase.getSleuthkitCase().getFileManager().findFilesExactNameExactPath(dataSource, + FilenameUtils.getName(downloadedFilePath), FilenameUtils.getPath(downloadedFilePath))) { bbartifacts.add(createAssociatedArtifact(downloadedFile, webDownloadArtifact)); break; } diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java index b0c119ae25..d9ad0fbfb8 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java @@ -152,13 +152,12 @@ class RecentDocumentsByLnk extends Extract { * @returnv BlackboardArtifact or a null value */ private BlackboardArtifact createAssociatedArtifact(String filePathName, BlackboardArtifact bba) { - org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager(); String normalizePathName = FilenameUtils.normalize(filePathName, true); String fileName = FilenameUtils.getName(normalizePathName); String filePath = FilenameUtils.getPath(normalizePathName); List sourceFiles; try { - sourceFiles = fileManager.findFiles(dataSource, fileName, filePath); //NON-NLS + sourceFiles = currentCase.getSleuthkitCase().getFileManager().findFilesExactNameExactPath(dataSource, fileName, filePath); for (AbstractFile sourceFile : sourceFiles) { if (sourceFile.getParentPath().endsWith(filePath)) { return createAssociatedArtifact(sourceFile, bba); diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Util.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Util.java index ff95c60ca8..766c3c61de 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Util.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Util.java @@ -135,8 +135,7 @@ class Util { parent_path = parent_path.substring(0, index); List files = null; try { - FileManager fileManager = Case.getCurrentCaseThrows().getServices().getFileManager(); - files = fileManager.findFiles(dataSource, name, parent_path); + files = Case.getCurrentCaseThrows().getSleuthkitCase().getFileManager().findFilesExactNameExactPath(dataSource, name, parent_path); } catch (TskCoreException | NoCurrentCaseException ex) { logger.log(Level.WARNING, "Error fetching 'index.data' files for Internet Explorer history."); //NON-NLS } diff --git a/release_scripts/localization_scripts/lastupdated.properties b/release_scripts/localization_scripts/lastupdated.properties index c31c7c9180..beebdc0034 100644 --- a/release_scripts/localization_scripts/lastupdated.properties +++ b/release_scripts/localization_scripts/lastupdated.properties @@ -1,2 +1,2 @@ -#Fri Feb 12 16:56:29 UTC 2021 -bundles.ja.lastupdated=c2a4ececfba59d230d1a263f7124e67f88e8d3e6 +#Mon Jun 14 12:23:19 UTC 2021 +bundles.ja.lastupdated=0952403cf485350f4db73ab6426ad5d6eb273e31 diff --git a/thirdparty/rr-full/plugins/samparse.pl b/thirdparty/rr-full/plugins/samparse.pl index 8046708b3b..f8997b632f 100644 --- a/thirdparty/rr-full/plugins/samparse.pl +++ b/thirdparty/rr-full/plugins/samparse.pl @@ -23,6 +23,7 @@ #----------------------------------------------------------- package samparse; use strict; +use Encode::Unicode; my %config = (hive => "SAM", hivemask => 2, @@ -364,7 +365,8 @@ sub _translateSID { #--------------------------------------------------------------------- sub _uniToAscii { my $str = $_[0]; - $str =~ s/\x00//g; + Encode::from_to($str,'UTF-16LE','utf8'); + $str = Encode::decode_utf8($str); return $str; }