From f5d65a4d39b706acc47897b047f370be22226dea Mon Sep 17 00:00:00 2001
From: Mark McKinnon <Mark.McKinnon13@outlook.com>
Date: Sun, 20 Aug 2023 10:44:33 -0400
Subject: [PATCH] FIx Merge Issues

Fix Merge Issues
---
 .../autopsy/malwarescan/Bundle.properties     |   7 +
 .../malwarescan/Bundle.properties-MERGED      |   9 +-
 .../malwarescan/MalwareScanIngestModule.java  |  28 ++--
 .../MalwareScanIngestModuleFactory.java       |  25 ++-
 .../MalwareScanIngestSettings.java            |  96 +++++++++++
 .../MalwareScanIngestSettingsPanel.form       | 123 +++++++++++++++
 .../MalwareScanIngestSettingsPanel.java       | 149 ++++++++++++++++++
 7 files changed, 421 insertions(+), 16 deletions(-)
 create mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties
 create mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettings.java
 create mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.form
 create mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.java

diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties
new file mode 100644
index 0000000000..fbf6db930c
--- /dev/null
+++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties
@@ -0,0 +1,7 @@
+MalwareScanIngestSettingsPanel.uploadFilesCheckbox.AccessibleContext.accessibleName=Upload file content for files that do not have results
+MalwareScanIngestSettingsPanel.uploadFilesCheckbox.label=Upload file content for files that do not have results
+MalwareScanIngestSettingsPanel.uploadFilesCheckbox.text=Upload file content for files that do not have results
+DataSourceIntegrityIngestSettingsPanel.queryFilesTextArea.text=Query for existing results using file\u2019s hash
+MalwareScanIngestSettingsPanel.ingestSettingsLabel.text=Ingest Settings
+MalwareScanIngestSettingsPanel.paidLicenseTextArea.text=This module requires a paid license. \nSee the Global Options panel for details
+MalwareScanIngestSettingsPanel.queryFilesCheckbox.text=Query for existing results using file\u2019s hash
diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties-MERGED b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties-MERGED
index 4380a9607c..decbae37cf 100644
--- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties-MERGED
+++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties-MERGED
@@ -38,6 +38,13 @@ MalwareScanIngestModule_uploadFile_noRemainingFileUploads_title=No Remaining Fil
 # {0} - objectId
 MalwareScanIngestModule_uploadFile_notUploadable_desc=A file did not meet requirements for upload (object id: {0}).
 MalwareScanIngestModule_uploadFile_notUploadable_title=Not Able to Upload
-MalwareScanIngestModuleFactory_description=The malware scan ingest module queries the Cyber Triage cloud API for any possible malicious executables.
+MalwareScanIngestModuleFactory_description=Identifies executable files with malware.
 MalwareScanIngestModuleFactory_displayName=Cyber Triage Malware Scanner
 MalwareScanIngestModuleFactory_version=1.0.0
+MalwareScanIngestSettingsPanel.uploadFilesCheckbox.AccessibleContext.accessibleName=Upload file content for files that do not have results
+MalwareScanIngestSettingsPanel.uploadFilesCheckbox.label=Upload file content for files that do not have results
+MalwareScanIngestSettingsPanel.uploadFilesCheckbox.text=Upload file content for files that do not have results
+DataSourceIntegrityIngestSettingsPanel.queryFilesTextArea.text=Query for existing results using file\u2019s hash
+MalwareScanIngestSettingsPanel.ingestSettingsLabel.text=Ingest Settings
+MalwareScanIngestSettingsPanel.paidLicenseTextArea.text=This module requires a paid license. \nSee the Global Options panel for details
+MalwareScanIngestSettingsPanel.queryFilesCheckbox.text=Query for existing results using file\u2019s hash
diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java
index 4698392478..190b1412ce 100644
--- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java
+++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java
@@ -72,10 +72,17 @@
 class MalwareScanIngestModule implements FileIngestModule {
 
     private static final SharedProcessing sharedProcessing = new SharedProcessing();
-
+    private boolean uploadFiles;
+    private boolean queryFiles;
+    
+    MalwareScanIngestModule(MalwareScanIngestSettings settings) {
+        uploadFiles = settings.shouldUploadFiles();
+        queryFiles = settings.shouldQueryFiles();  
+    }
+    
     @Override
     public void startUp(IngestJobContext context) throws IngestModuleException {
-        sharedProcessing.startUp(context);
+        sharedProcessing.startUp(context, uploadFiles);
     }
 
     @Override
@@ -123,7 +130,7 @@ private static class SharedProcessing {
                 "application/msdos-windows",//NON-NLS
                 "application/x-msdos-program"//NON-NLS
         ).collect(Collectors.toSet());
-
+        
         private static final String MALWARE_TYPE_NAME = "TSK_MALWARE";
         private static final String MALWARE_CONFIG = "Cyber Triage Cloud";
 
@@ -153,14 +160,14 @@ private static class SharedProcessing {
             "MalwareScanIngestModule_ShareProcessing_lowUploadsLimitWarning_title=File Uploads Limit Low",
             "# {0} - remainingUploads",
             "MalwareScanIngestModule_ShareProcessing_lowUploadsLimitWarning_desc=This license only has {0} file uploads remaining.",})
-        synchronized void startUp(IngestJobContext context) throws IngestModuleException {
+        synchronized void startUp(IngestJobContext context, boolean uploadFiles) throws IngestModuleException {
             // only run this code once per startup
             if (ingestJobState != null) {
                 return;
             }
 
             try {
-                ingestJobState = getNewJobState(context);
+                ingestJobState = getNewJobState(context, uploadFiles);
             } catch (Exception ex) {
                 ingestJobState = IngestJobState.DISABLED;
                 throw new IngestModuleException("An exception occurred on MalwareScanIngestModule startup", ex);
@@ -175,7 +182,7 @@ synchronized void startUp(IngestJobContext context) throws IngestModuleException
          * parameters required for the job.
          * @throws Exception
          */
-        private IngestJobState getNewJobState(IngestJobContext context) throws Exception {
+        private IngestJobState getNewJobState(IngestJobContext context, boolean uploadFiles) throws Exception {
             // get saved license
             Optional<LicenseInfo> licenseInfoOpt = ctSettingsPersistence.loadLicenseInfo();
             if (licenseInfoOpt.isEmpty() || licenseInfoOpt.get().getDecryptedLicense() == null) {
@@ -207,7 +214,6 @@ private IngestJobState getNewJobState(IngestJobContext context) throws Exception
             }
 
             // determine lookups remaining
-            boolean uploadFiles = ctSettingsPersistence.loadMalwareIngestSettings().isUploadFiles();
             if (uploadFiles) {
                 long uploadsRemaining = remaining(authTokenResponse.getFileUploadLimit(), authTokenResponse.getFileUploadCount());
                 if (uploadsRemaining <= 0) {
@@ -775,11 +781,7 @@ private void createAnalysisResults(IngestJobState ingestJobState, List<CTCloudBe
                     for (Long objId : objIds) {
                         AnalysisResult res = createAnalysisResult(ingestJobState, trans, result, objId);
                         if (res != null) {
-                            // only post results that have score NOTABLE or LIKELY_NOTABLE
-                            Score score = res.getScore();
-                            if (score.getSignificance() == Score.Significance.NOTABLE || score.getSignificance() == Score.Significance.LIKELY_NOTABLE) {
-                                createdArtifacts.add(res);
-                            }
+                            createdArtifacts.add(res);
                         }
                     }
                 }
@@ -841,7 +843,7 @@ private AnalysisResult createAnalysisResult(IngestJobState ingestJobState, Sleut
                     : Bundle.MalwareScanIngestModule_SharedProcessing_createAnalysisResult_No();
 
             String justification = cloudBean.getMalwareResult().getStatusDescription();
-            
+
             return ingestJobState.getTskCase().getBlackboard().newAnalysisResult(
                     ingestJobState.getMalwareType(),
                     objId,
diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModuleFactory.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModuleFactory.java
index e138116036..83cb93f689 100644
--- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModuleFactory.java
+++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModuleFactory.java
@@ -25,6 +25,8 @@
 import org.sleuthkit.autopsy.ingest.IngestModuleFactoryAdapter;
 import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSettingsPanel;
 import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
+import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel;
+import org.sleuthkit.autopsy.ingest.NoIngestModuleIngestJobSettings;
 
 /**
  * Factory for malware scan ingest modules.
@@ -32,7 +34,7 @@
 @ServiceProvider(service = org.sleuthkit.autopsy.ingest.IngestModuleFactory.class)
 @Messages({
     "MalwareScanIngestModuleFactory_displayName=Cyber Triage Malware Scanner",
-    "MalwareScanIngestModuleFactory_description=The malware scan ingest module queries the Cyber Triage cloud API for any possible malicious executables.",
+    "MalwareScanIngestModuleFactory_description=Identifies executable files with malware.",
     "MalwareScanIngestModuleFactory_version=1.0.0"
 })
 public class MalwareScanIngestModuleFactory extends IngestModuleFactoryAdapter {
@@ -66,7 +68,7 @@ public boolean isFileIngestModuleFactory() {
 
     @Override
     public FileIngestModule createFileIngestModule(IngestModuleIngestJobSettings ingestOptions) {
-        return new MalwareScanIngestModule();
+        return new MalwareScanIngestModule((MalwareScanIngestSettings) ingestOptions);
     }
 
     @Override
@@ -81,4 +83,23 @@ public IngestModuleGlobalSettingsPanel getGlobalSettingsPanel() {
         return optionsPanel;
     }
 
+    @Override
+    public boolean hasIngestJobSettingsPanel() {
+        return true;
+    }
+
+    @Override
+    public IngestModuleIngestJobSettingsPanel getIngestJobSettingsPanel(IngestModuleIngestJobSettings settings) {
+        if (settings instanceof MalwareScanIngestSettings) {
+            return new MalwareScanIngestSettingsPanel((MalwareScanIngestSettings) settings);
+        }
+        /*
+         * Compatibility check for older versions.
+         */
+        if (settings instanceof NoIngestModuleIngestJobSettings) {
+            return new MalwareScanIngestSettingsPanel(new MalwareScanIngestSettings());
+        }
+        
+        throw new IllegalArgumentException("Expected settings argument to be an instance of IngestSettings");
+    }
 }
diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettings.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettings.java
new file mode 100644
index 0000000000..158e967745
--- /dev/null
+++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettings.java
@@ -0,0 +1,96 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2023 Basis Technology Corp.
+ * Contact: carrier <at> sleuthkit <dot> org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.basistech.df.cybertriage.autopsy.malwarescan;
+
+import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
+
+/**
+ * Ingest job settings for the Malware scanner module.
+ */
+final class MalwareScanIngestSettings implements IngestModuleIngestJobSettings {
+
+    private static final long serialVersionUID = 1L;
+
+    private static final boolean DEFAULT_QUERY_FILES = true;
+    private static final boolean DEFAULT_UPLOAD_FILES = true;
+    
+    public boolean queryFiles;
+    public boolean uploadFiles;
+
+    /**
+     * Instantiate the ingest job settings with default values.
+     */
+    MalwareScanIngestSettings() {
+        this.queryFiles = DEFAULT_QUERY_FILES;
+        this.uploadFiles = DEFAULT_UPLOAD_FILES;
+    }
+
+    /**
+     * Instantiate the ingest job settings.
+     * 
+     * @param computeHashes  Compute hashes if none are present
+     * @param verifyHashes   Verify hashes if any are present
+     */
+    MalwareScanIngestSettings(boolean queryFiles, boolean uploadFiles) {
+        this.queryFiles = queryFiles;
+        this.uploadFiles = uploadFiles;
+    }
+
+    @Override
+    public long getVersionNumber() {
+        return serialVersionUID;
+    }
+    
+    /**
+     * Should files be queried?
+     * 
+     * @return true if files should be queried, false otherwise
+     */
+    public boolean shouldQueryFiles() {
+        return queryFiles;
+    }
+    
+    /**
+     * Set whether files should be queried.
+     * 
+     * @param queryFiles true if files should be queried
+     */
+    void setqueryFiles(boolean queryFiles) {
+        this.queryFiles = queryFiles;
+    }
+    
+    
+    /**
+     * Should files be uploaded?
+     * 
+     * @return true if files should be uploaded, false otherwise
+     */
+    public boolean shouldUploadFiles() {
+        return uploadFiles;
+    }    
+    
+    /**
+     * Set whether files should be uploaded.
+     * 
+     * @param uploadFiles true if files should be uploaded
+     */
+    void setUploadFiles(boolean uploadFiles) {
+        this.uploadFiles = uploadFiles;
+    }
+}
diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.form b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.form
new file mode 100644
index 0000000000..46a928c98e
--- /dev/null
+++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.form
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+  <Properties>
+    <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+      <Dimension value="[300, 155]"/>
+    </Property>
+  </Properties>
+  <AuxValues>
+    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+  </AuxValues>
+
+  <Layout>
+    <DimensionLayout dim="0">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" attributes="0">
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <Group type="102" attributes="0">
+                      <EmptySpace min="6" pref="6" max="-2" attributes="0"/>
+                      <Component id="ingestSettingsLabel" min="-2" max="-2" attributes="0"/>
+                  </Group>
+                  <Group type="102" attributes="0">
+                      <EmptySpace min="6" pref="6" max="-2" attributes="0"/>
+                      <Component id="uploadFilesCheckbox" min="-2" max="-2" attributes="0"/>
+                  </Group>
+                  <Group type="102" alignment="0" attributes="0">
+                      <EmptySpace max="-2" attributes="0"/>
+                      <Component id="queryFilesCheckbox" min="-2" max="-2" attributes="0"/>
+                  </Group>
+                  <Group type="102" alignment="0" attributes="0">
+                      <EmptySpace min="-2" pref="5" max="-2" attributes="0"/>
+                      <Component id="paidLicenseTextArea" min="-2" pref="243" max="-2" attributes="0"/>
+                  </Group>
+              </Group>
+              <EmptySpace min="-2" pref="185" max="-2" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+    <DimensionLayout dim="1">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" attributes="0">
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="ingestSettingsLabel" min="-2" max="-2" attributes="0"/>
+              <EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
+              <Component id="queryFilesCheckbox" min="-2" max="-2" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="uploadFilesCheckbox" min="-2" max="-2" attributes="0"/>
+              <EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
+              <Component id="paidLicenseTextArea" min="-2" pref="32" max="-2" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+  </Layout>
+  <SubComponents>
+    <Component class="javax.swing.JCheckBox" name="queryFilesCheckbox">
+      <Properties>
+        <Property name="selected" type="boolean" value="true"/>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties" key="MalwareScanIngestSettingsPanel.queryFilesCheckbox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+        <Property name="enabled" type="boolean" value="false"/>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JCheckBox" name="uploadFilesCheckbox">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties" key="MalwareScanIngestSettingsPanel.uploadFilesCheckbox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+        <Property name="focusable" type="boolean" value="false"/>
+        <Property name="label" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties" key="MalwareScanIngestSettingsPanel.uploadFilesCheckbox.label" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+      <AccessibilityProperties>
+        <Property name="AccessibleContext.accessibleName" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties" key="MalwareScanIngestSettingsPanel.uploadFilesCheckbox.AccessibleContext.accessibleName" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </AccessibilityProperties>
+    </Component>
+    <Component class="javax.swing.JLabel" name="ingestSettingsLabel">
+      <Properties>
+        <Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
+          <FontInfo relative="true">
+            <Font bold="true" component="ingestSettingsLabel" property="font" relativeSize="true" size="0"/>
+          </FontInfo>
+        </Property>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties" key="MalwareScanIngestSettingsPanel.ingestSettingsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JTextArea" name="paidLicenseTextArea">
+      <Properties>
+        <Property name="columns" type="int" value="20"/>
+        <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+          <Font name="Segoe UI" size="12" style="1"/>
+        </Property>
+        <Property name="rows" type="int" value="5"/>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties" key="MalwareScanIngestSettingsPanel.paidLicenseTextArea.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+        <Property name="wrapStyleWord" type="boolean" value="true"/>
+        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+          <Border info="null"/>
+        </Property>
+        <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
+          <Color id="Default Cursor"/>
+        </Property>
+        <Property name="focusable" type="boolean" value="false"/>
+        <Property name="opaque" type="boolean" value="false"/>
+        <Property name="requestFocusEnabled" type="boolean" value="false"/>
+      </Properties>
+    </Component>
+  </SubComponents>
+</Form>
diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.java
new file mode 100644
index 0000000000..a418de0f83
--- /dev/null
+++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.java
@@ -0,0 +1,149 @@
+/*
+ * Autopsy Browser
+ *
+ * Copyright 2023 Basis Technology Corp.
+ * Contact: carrier <at> sleuthkit <dot> org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.basistech.df.cybertriage.autopsy.malwarescan;
+
+import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseInfo;
+import com.basistech.df.cybertriage.autopsy.ctoptions.ctcloud.CTLicensePersistence;
+import java.util.Optional;
+import org.sleuthkit.autopsy.modules.dataSourceIntegrity.*;
+import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
+import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel;
+
+/**
+ * Ingest job settings panel for the Malware scanner ingest.
+ */
+@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
+final class MalwareScanIngestSettingsPanel extends IngestModuleIngestJobSettingsPanel {
+
+    private final CTLicensePersistence ctPersistence = CTLicensePersistence.getInstance();
+    
+    MalwareScanIngestSettingsPanel(MalwareScanIngestSettings settings) {
+        initComponents();
+        customizeComponents(settings);
+    }
+
+    /**
+     * Update components with values from the ingest job settings.
+     *
+     * @param settings The ingest job settings.
+     */
+    private void customizeComponents(MalwareScanIngestSettings settings) {
+        Optional<LicenseInfo> licenseInfoOpt = ctPersistence.loadLicenseInfo();
+        LicenseInfo licenseInfo = licenseInfoOpt.orElse(null);
+        if (licenseInfo != null) {
+            this.paidLicenseTextArea.setVisible(false);
+            this.queryFilesCheckbox.setVisible(true);
+            this.queryFilesCheckbox.setEnabled(false);
+            this.uploadFilesCheckbox.setVisible(true);
+            this.queryFilesCheckbox.setSelected(true);
+            this.uploadFilesCheckbox.setSelected(settings.shouldUploadFiles());
+        } else {
+            this.paidLicenseTextArea.setVisible(true);
+            this.queryFilesCheckbox.setVisible(false);
+            this.uploadFilesCheckbox.setVisible(false);       
+        }
+    }
+    
+    @Override
+    public IngestModuleIngestJobSettings getSettings() {
+        return new MalwareScanIngestSettings(queryFilesCheckbox.isSelected(), uploadFilesCheckbox.isSelected());
+    }
+
+    /**
+     * This method is called from within the constructor to initialize the form.
+     * WARNING: Do NOT modify this code. The content of this method is always
+     * regenerated by the Form Editor.
+     */
+    @SuppressWarnings("unchecked")
+    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+    private void initComponents() {
+
+        queryFilesCheckbox = new javax.swing.JCheckBox();
+        uploadFilesCheckbox = new javax.swing.JCheckBox();
+        ingestSettingsLabel = new javax.swing.JLabel();
+        paidLicenseTextArea = new javax.swing.JTextArea();
+
+        setPreferredSize(new java.awt.Dimension(300, 155));
+
+        queryFilesCheckbox.setSelected(true);
+        org.openide.awt.Mnemonics.setLocalizedText(queryFilesCheckbox, org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.queryFilesCheckbox.text")); // NOI18N
+        queryFilesCheckbox.setEnabled(false);
+
+        org.openide.awt.Mnemonics.setLocalizedText(uploadFilesCheckbox, org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.uploadFilesCheckbox.text")); // NOI18N
+        uploadFilesCheckbox.setFocusable(false);
+        uploadFilesCheckbox.setLabel(org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.uploadFilesCheckbox.label")); // NOI18N
+
+        ingestSettingsLabel.setFont(ingestSettingsLabel.getFont().deriveFont(ingestSettingsLabel.getFont().getStyle() | java.awt.Font.BOLD));
+        org.openide.awt.Mnemonics.setLocalizedText(ingestSettingsLabel, org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.ingestSettingsLabel.text")); // NOI18N
+
+        paidLicenseTextArea.setColumns(20);
+        paidLicenseTextArea.setFont(new java.awt.Font("Segoe UI", 1, 12)); // NOI18N
+        paidLicenseTextArea.setRows(5);
+        paidLicenseTextArea.setText(org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.paidLicenseTextArea.text")); // NOI18N
+        paidLicenseTextArea.setWrapStyleWord(true);
+        paidLicenseTextArea.setBorder(null);
+        paidLicenseTextArea.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
+        paidLicenseTextArea.setFocusable(false);
+        paidLicenseTextArea.setOpaque(false);
+        paidLicenseTextArea.setRequestFocusEnabled(false);
+
+        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+        this.setLayout(layout);
+        layout.setHorizontalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(layout.createSequentialGroup()
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addGroup(layout.createSequentialGroup()
+                        .addGap(6, 6, 6)
+                        .addComponent(ingestSettingsLabel))
+                    .addGroup(layout.createSequentialGroup()
+                        .addGap(6, 6, 6)
+                        .addComponent(uploadFilesCheckbox))
+                    .addGroup(layout.createSequentialGroup()
+                        .addContainerGap()
+                        .addComponent(queryFilesCheckbox))
+                    .addGroup(layout.createSequentialGroup()
+                        .addGap(5, 5, 5)
+                        .addComponent(paidLicenseTextArea, javax.swing.GroupLayout.PREFERRED_SIZE, 243, javax.swing.GroupLayout.PREFERRED_SIZE)))
+                .addGap(185, 185, 185))
+        );
+        layout.setVerticalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(layout.createSequentialGroup()
+                .addContainerGap()
+                .addComponent(ingestSettingsLabel)
+                .addGap(18, 18, 18)
+                .addComponent(queryFilesCheckbox)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(uploadFilesCheckbox)
+                .addGap(18, 18, 18)
+                .addComponent(paidLicenseTextArea, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE))
+        );
+
+        uploadFilesCheckbox.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.uploadFilesCheckbox.AccessibleContext.accessibleName")); // NOI18N
+    }// </editor-fold>//GEN-END:initComponents
+
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    private javax.swing.JLabel ingestSettingsLabel;
+    private javax.swing.JTextArea paidLicenseTextArea;
+    private javax.swing.JCheckBox queryFilesCheckbox;
+    private javax.swing.JCheckBox uploadFilesCheckbox;
+    // End of variables declaration//GEN-END:variables
+
+}
-- 
GitLab