From 6c4de46738ae104b11eca70cb3079536785aa7a1 Mon Sep 17 00:00:00 2001
From: "U-BASIS\\dsmyda" <dsmyda@win-dsmyd-2925.basistech.net>
Date: Wed, 25 Nov 2020 10:16:54 -0500
Subject: [PATCH] Moved the file repo classes back to datamodel and put the
 temp directory back

---
 .../org/sleuthkit/datamodel/AbstractFile.java |  14 +--
 .../BulkExistenceEnum.java                    |   2 +-
 .../BulkExistenceResult.java                  |   3 +-
 .../org/sleuthkit/datamodel/Bundle.properties |   3 +
 .../datamodel/Bundle.properties-MERGED        |   3 +
 .../{filerepository => }/FileRepository.java  | 102 +++++++++++++-----
 .../FileRepositoryErrorHandler.java           |   2 +-
 .../FileRepositoryException.java              |   2 +-
 .../FileRepositorySettings.java               |   2 +-
 .../filerepository/Bundle.properties          |   3 -
 .../filerepository/Bundle.properties-MERGED   |   3 -
 11 files changed, 89 insertions(+), 50 deletions(-)
 rename bindings/java/src/org/sleuthkit/datamodel/{filerepository => }/BulkExistenceEnum.java (95%)
 rename bindings/java/src/org/sleuthkit/datamodel/{filerepository => }/BulkExistenceResult.java (93%)
 rename bindings/java/src/org/sleuthkit/datamodel/{filerepository => }/FileRepository.java (82%)
 rename bindings/java/src/org/sleuthkit/datamodel/{filerepository => }/FileRepositoryErrorHandler.java (95%)
 rename bindings/java/src/org/sleuthkit/datamodel/{filerepository => }/FileRepositoryException.java (94%)
 rename bindings/java/src/org/sleuthkit/datamodel/{filerepository => }/FileRepositorySettings.java (96%)
 delete mode 100755 bindings/java/src/org/sleuthkit/datamodel/filerepository/Bundle.properties
 delete mode 100755 bindings/java/src/org/sleuthkit/datamodel/filerepository/Bundle.properties-MERGED

diff --git a/bindings/java/src/org/sleuthkit/datamodel/AbstractFile.java b/bindings/java/src/org/sleuthkit/datamodel/AbstractFile.java
index 9696a7c30..a8911a3e7 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/AbstractFile.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/AbstractFile.java
@@ -18,7 +18,6 @@
  */
 package org.sleuthkit.datamodel;
 
-import org.sleuthkit.datamodel.filerepository.FileRepository;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
@@ -27,11 +26,11 @@
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
 import java.sql.SQLException;
 import java.sql.Statement;
 import java.text.MessageFormat;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 import java.util.ResourceBundle;
 import java.util.Set;
@@ -44,7 +43,6 @@
 import org.sleuthkit.datamodel.TskData.TSK_FS_META_TYPE_ENUM;
 import org.sleuthkit.datamodel.TskData.TSK_FS_NAME_FLAG_ENUM;
 import org.sleuthkit.datamodel.TskData.TSK_FS_NAME_TYPE_ENUM;
-import org.sleuthkit.datamodel.filerepository.FileRepositoryException;
 
 /**
  * An abstract base class for classes that represent files that have been added
@@ -1081,14 +1079,12 @@ private synchronized void loadLocalFile() throws TskCoreException {
 				throw new TskCoreException("Previously failed to load file with object ID " + getId() + " from file repository.");
 			}
 			
-			// Copy the file from the server
-			Path localFilePath = Paths.get(System.getProperty("java.io.tmpdir"), this.getSha256Hash());
 			try (InputStream fileRepositoryStream = FileRepository.download(this)) {
-				Files.copy(fileRepositoryStream, localFilePath);
+				Path localFilePath = Paths.get(FileRepository.getTempDirectory().getAbsolutePath(), this.getSha256Hash());
+				if (!Files.exists(localFilePath)) {
+					Files.copy(fileRepositoryStream, localFilePath);
+				}
 				localFile = localFilePath.toFile();
-			} catch (FileAlreadyExistsException ex) {
-				// Do nothing, file already exists.
-				this.localFile = localFilePath.toFile();
 			} catch (FileRepositoryException | IOException ex) {
 				// If we've failed to download from the file repository, don't try again for this session.
 				errorLoadingFromFileRepo = true;
diff --git a/bindings/java/src/org/sleuthkit/datamodel/filerepository/BulkExistenceEnum.java b/bindings/java/src/org/sleuthkit/datamodel/BulkExistenceEnum.java
similarity index 95%
rename from bindings/java/src/org/sleuthkit/datamodel/filerepository/BulkExistenceEnum.java
rename to bindings/java/src/org/sleuthkit/datamodel/BulkExistenceEnum.java
index c6e30283b..e43718da4 100755
--- a/bindings/java/src/org/sleuthkit/datamodel/filerepository/BulkExistenceEnum.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/BulkExistenceEnum.java
@@ -16,7 +16,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.sleuthkit.datamodel.filerepository;
+package org.sleuthkit.datamodel;
 
 /**
  * Represents the states of existence for a file in the file repository.
diff --git a/bindings/java/src/org/sleuthkit/datamodel/filerepository/BulkExistenceResult.java b/bindings/java/src/org/sleuthkit/datamodel/BulkExistenceResult.java
similarity index 93%
rename from bindings/java/src/org/sleuthkit/datamodel/filerepository/BulkExistenceResult.java
rename to bindings/java/src/org/sleuthkit/datamodel/BulkExistenceResult.java
index 9effcb9f3..b35851392 100755
--- a/bindings/java/src/org/sleuthkit/datamodel/filerepository/BulkExistenceResult.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/BulkExistenceResult.java
@@ -16,11 +16,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.sleuthkit.datamodel.filerepository;
+package org.sleuthkit.datamodel;
 
 import java.util.Collections;
 import java.util.Map;
-import org.sleuthkit.datamodel.AbstractFile;
 
 /**
  * Container for bulk existence results.
diff --git a/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties b/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties
index d36df3e0b..3d3265735 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties
+++ b/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties
@@ -354,3 +354,6 @@ tagsFilter.displayName.text=Must be tagged
 TextFilter.displayName.text=Must include text:
 TypeFilter.displayName.text=Limit event types to
 FileTypesFilter.displayName.text=Limit file types to
+FileRepository.error.title.text=Error from file repository
+FileRepository.downloadError.msg.text=Encountered unexpected error from the file repository. Please see logs for more information.
+FileRepository.notEnabled.msg.text=File repository is not enabled
\ No newline at end of file
diff --git a/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties-MERGED b/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties-MERGED
index d36df3e0b..3d3265735 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties-MERGED
+++ b/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties-MERGED
@@ -354,3 +354,6 @@ tagsFilter.displayName.text=Must be tagged
 TextFilter.displayName.text=Must include text:
 TypeFilter.displayName.text=Limit event types to
 FileTypesFilter.displayName.text=Limit file types to
+FileRepository.error.title.text=Error from file repository
+FileRepository.downloadError.msg.text=Encountered unexpected error from the file repository. Please see logs for more information.
+FileRepository.notEnabled.msg.text=File repository is not enabled
\ No newline at end of file
diff --git a/bindings/java/src/org/sleuthkit/datamodel/filerepository/FileRepository.java b/bindings/java/src/org/sleuthkit/datamodel/FileRepository.java
similarity index 82%
rename from bindings/java/src/org/sleuthkit/datamodel/filerepository/FileRepository.java
rename to bindings/java/src/org/sleuthkit/datamodel/FileRepository.java
index 5b862e176..557145a3e 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/filerepository/FileRepository.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/FileRepository.java
@@ -16,9 +16,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.sleuthkit.datamodel.filerepository;
+package org.sleuthkit.datamodel;
 
 import com.google.gson.Gson;
+import java.io.File;
 import java.io.BufferedReader;
 import java.io.ByteArrayOutputStream;
 import java.io.FilterInputStream;
@@ -33,6 +34,8 @@
 import java.util.List;
 import java.util.ResourceBundle;
 import java.util.UUID;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 import java.util.stream.Collectors;
 import org.apache.http.HttpEntity;
 import org.apache.http.HttpStatus;
@@ -46,50 +49,86 @@
 import org.apache.http.entity.mime.MultipartEntityBuilder;
 import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.http.impl.client.HttpClients;
-import org.sleuthkit.datamodel.AbstractFile;
-import org.sleuthkit.datamodel.TskData;
 
 /**
  * Class to represent a file repository.
  */
 public class FileRepository {
 
-	private static final ResourceBundle BUNDLE = ResourceBundle.getBundle("org.sleuthkit.datamodel.filerepository.Bundle");
+	private static final Logger logger = Logger.getLogger(FileRepository.class.getName());
+	private static final ResourceBundle BUNDLE = ResourceBundle.getBundle("org.sleuthkit.datamodel.Bundle");
 	private static final int MAX_BULK_QUERY_SIZE = 500;
 	private final static String V1_FILES_TEMPLATE = "http://%s:%s/v1/files/";
 	
 	private final Gson gson;
 	private final FileRepositorySettings settings;
+	private final File fileDownloadFolder;
 	
 	private static FileRepositoryErrorHandler errorHandler;
 	private static FileRepository instance;
 
-	/**
-	 * Create the file repository.
-	 *
-	 * @param settings         The file repository settings
-	 * @param fileDownloadPath The temporary folder to download files to from
-	 *                         the repository
-	 */
-	FileRepository(FileRepositorySettings settings) {
-		this.settings = settings;
+	/**	
+     * Create the file repository.	
+     *	
+     * @param settings          The file repository settings	
+     * @param fileDownloadPath  The temporary folder to download files to from the repository	
+     */	
+	private FileRepository(FileRepositorySettings settings, File fileDownloadPath) {	
+		this.settings = settings;	
+		this.fileDownloadFolder = fileDownloadPath;	
 		this.gson = new Gson();
 	}
+	
+	/**	
+	 * Delete the folder of downloaded files.	
+	 */	
+	private static synchronized void deleteDownloadFolder(File dirPath) {	
+        if (dirPath.isDirectory() == false || dirPath.exists() == false) {	
+            return;	
+        }	
+
+        File[] files = dirPath.listFiles();	
+        if (files != null) {	
+            for (File file : files) {	
+                if (file.isDirectory()) {	
+                    deleteDownloadFolder(file);	
+                } else {	
+                    if (file.delete() == false) {	
+                        logger.log(Level.WARNING, "Failed to delete file {0}", file.getPath()); //NON-NLS	
+                    }	
+                }	
+            }	
+        }	
+        if (dirPath.delete() == false) {	
+            logger.log(Level.WARNING, "Failed to delete the empty directory at {0}", dirPath.getPath()); //NON-NLS	
+        }	
+	}
 
-	/**
-	 * Initializes the file repository.
-	 *
-	 * @param settings The file repository settings
-	 */
-	public static synchronized void initialize(FileRepositorySettings settings) {
-		instance = new FileRepository(settings);
+	/**	
+     * Initializes the file repository.	
+     *	
+     * @param settings          The file repository settings	
+     * @param fileDownloadPath  The temporary folder to download files to from the repository	
+     */		
+	public static synchronized void initialize(FileRepositorySettings settings, File fileDownloadPath) {	
+		// If the download path is changing, delete any files in the old one	
+		if ((instance != null) && (instance.fileDownloadFolder != null)	
+				&& ( ! instance.fileDownloadFolder.equals(fileDownloadPath))) {	
+			deleteDownloadFolder(instance.fileDownloadFolder);	
+		}	
+		instance = new FileRepository(settings, fileDownloadPath);	
 	}
 
-	/**
-	 * De-initializes the file repository.
-	 */
-	public static synchronized void deinitialize() {
-		instance = null;
+	/**	
+     * De-initializes the file repository.	
+     */		
+	public static synchronized void deinitialize() {	
+		if (instance != null) {	
+			// Delete the temp folder	
+			deleteDownloadFolder(instance.fileDownloadFolder);	
+		}	
+
+		instance = null;	
 	}
 
 	/**
@@ -109,6 +148,11 @@ public static boolean isEnabled() {
 	public static synchronized void setErrorHandler(FileRepositoryErrorHandler handler) {
 		errorHandler = handler;
 	}
+	
+	static synchronized File getTempDirectory() throws FileRepositoryException {
+		ensureInstanceIsEnabled();
+		return instance.fileDownloadFolder;
+	}
 
 	/**
 	 * Report an error to the user. The idea is to use this for cases where it's
@@ -132,7 +176,7 @@ private static synchronized void reportError(String errorTitle, String errorStr)
 	 *
 	 * @return The file contents, as a stream.
 	 *
-	 * @throws org.sleuthkit.datamodel.filerepository.FileRepositoryException
+	 * @throws org.sleuthkit.datamodel.FileRepositoryException
 	 * @throws java.io.IOException
 	 *
 	 */
@@ -201,7 +245,7 @@ private InputStream sendDownloadRequest(String SHA256) throws IOException, FileR
 	 * @param stream Arbitrary data to store in this file repository.
 	 *
 	 * @throws java.io.IOException
-	 * @throws org.sleuthkit.datamodel.filerepository.FileRepositoryException
+	 * @throws org.sleuthkit.datamodel.FileRepositoryException
 	 */
 	public static synchronized void upload(InputStream stream) throws IOException, FileRepositoryException {
 		// Preconditions
@@ -218,7 +262,7 @@ private void sendUploadRequest(InputStream stream) throws IOException, FileRepos
 			final String uploadURL = settings.createBaseURL(V1_FILES_TEMPLATE);
 
 			// Flush the stream to a local temp file for transport.
-			final Path temp = Paths.get(System.getProperty("java.io.tmpdir"), UUID.randomUUID().toString());
+			final Path temp = Paths.get(fileDownloadFolder.getAbsolutePath(), UUID.randomUUID().toString());
 			Files.copy(stream, temp);
 
 			final HttpEntity fileUpload = MultipartEntityBuilder.create()
@@ -257,7 +301,7 @@ private void sendUploadRequest(InputStream stream) throws IOException, FileRepos
 	 * @return An object encapsulating the response for each file.
 	 *
 	 * @throws java.io.IOException
-	 * @throws org.sleuthkit.datamodel.filerepository.FileRepositoryException
+	 * @throws org.sleuthkit.datamodel.FileRepositoryException
 	 */
 	public static synchronized BulkExistenceResult exists(List<AbstractFile> files) throws IOException, FileRepositoryException {
 		// Preconditions
diff --git a/bindings/java/src/org/sleuthkit/datamodel/filerepository/FileRepositoryErrorHandler.java b/bindings/java/src/org/sleuthkit/datamodel/FileRepositoryErrorHandler.java
similarity index 95%
rename from bindings/java/src/org/sleuthkit/datamodel/filerepository/FileRepositoryErrorHandler.java
rename to bindings/java/src/org/sleuthkit/datamodel/FileRepositoryErrorHandler.java
index b58a4b064..341a6f4b8 100755
--- a/bindings/java/src/org/sleuthkit/datamodel/filerepository/FileRepositoryErrorHandler.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/FileRepositoryErrorHandler.java
@@ -16,7 +16,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.sleuthkit.datamodel.filerepository;
+package org.sleuthkit.datamodel;
 
 /**
  * Callback class to use for error reporting.
diff --git a/bindings/java/src/org/sleuthkit/datamodel/filerepository/FileRepositoryException.java b/bindings/java/src/org/sleuthkit/datamodel/FileRepositoryException.java
similarity index 94%
rename from bindings/java/src/org/sleuthkit/datamodel/filerepository/FileRepositoryException.java
rename to bindings/java/src/org/sleuthkit/datamodel/FileRepositoryException.java
index b3b1f6657..df66e7a7a 100755
--- a/bindings/java/src/org/sleuthkit/datamodel/filerepository/FileRepositoryException.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/FileRepositoryException.java
@@ -16,7 +16,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.sleuthkit.datamodel.filerepository;
+package org.sleuthkit.datamodel;
 
 public class FileRepositoryException extends Exception {
 	
diff --git a/bindings/java/src/org/sleuthkit/datamodel/filerepository/FileRepositorySettings.java b/bindings/java/src/org/sleuthkit/datamodel/FileRepositorySettings.java
similarity index 96%
rename from bindings/java/src/org/sleuthkit/datamodel/filerepository/FileRepositorySettings.java
rename to bindings/java/src/org/sleuthkit/datamodel/FileRepositorySettings.java
index 8bbfa0729..8b64881f7 100755
--- a/bindings/java/src/org/sleuthkit/datamodel/filerepository/FileRepositorySettings.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/FileRepositorySettings.java
@@ -16,7 +16,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.sleuthkit.datamodel.filerepository;
+package org.sleuthkit.datamodel;
 
 /**
  * Utility class to hold the file repository server settings.
diff --git a/bindings/java/src/org/sleuthkit/datamodel/filerepository/Bundle.properties b/bindings/java/src/org/sleuthkit/datamodel/filerepository/Bundle.properties
deleted file mode 100755
index 801211667..000000000
--- a/bindings/java/src/org/sleuthkit/datamodel/filerepository/Bundle.properties
+++ /dev/null
@@ -1,3 +0,0 @@
-FileRepository.error.title.text=Error from file repository
-FileRepository.downloadError.msg.text=Encountered unexpected error from the file repository. Please see logs for more information.
-FileRepository.notEnabled.msg.text=File repository is not enabled
\ No newline at end of file
diff --git a/bindings/java/src/org/sleuthkit/datamodel/filerepository/Bundle.properties-MERGED b/bindings/java/src/org/sleuthkit/datamodel/filerepository/Bundle.properties-MERGED
deleted file mode 100755
index 801211667..000000000
--- a/bindings/java/src/org/sleuthkit/datamodel/filerepository/Bundle.properties-MERGED
+++ /dev/null
@@ -1,3 +0,0 @@
-FileRepository.error.title.text=Error from file repository
-FileRepository.downloadError.msg.text=Encountered unexpected error from the file repository. Please see logs for more information.
-FileRepository.notEnabled.msg.text=File repository is not enabled
\ No newline at end of file
-- 
GitLab