From 53cf29a0760a2861927e19ee5085c8e25add11a3 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Tue, 21 Jul 2015 09:33:05 -0400 Subject: [PATCH 1/3] Moved getLocalHostName into NetworkUtils. Renamed SingleUserCaseImporter. Moved TimeStampUtils into coreutils. Removed unused TimestampingFormatter class. Removed public from XMLCaseManagement. --- .../sleuthkit/autopsy/casemodule/Case.java | 30 ++----- .../casemodule/CollaborationMonitor.java | 21 +---- ...erter.java => SingleUserCaseImporter.java} | 80 ++++++++++++------- .../autopsy/casemodule/XMLCaseManagement.java | 2 +- .../autopsy/coreutils/NetworkUtils.java | 43 ++++++++++ .../TimeStampUtils.java | 6 +- .../coreutils/TimestampingFormatter.java | 50 ------------ 7 files changed, 105 insertions(+), 127 deletions(-) rename Core/src/org/sleuthkit/autopsy/casemodule/{CaseConverter.java => SingleUserCaseImporter.java} (93%) create mode 100644 Core/src/org/sleuthkit/autopsy/coreutils/NetworkUtils.java rename Core/src/org/sleuthkit/autopsy/{casemodule => coreutils}/TimeStampUtils.java (87%) delete mode 100644 Core/src/org/sleuthkit/autopsy/coreutils/TimestampingFormatter.java diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index f28acaae03..b67c7d0436 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -60,6 +60,7 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.coreutils.Version; +import org.sleuthkit.autopsy.coreutils.NetworkUtils; import org.sleuthkit.autopsy.events.AutopsyEvent; import org.sleuthkit.autopsy.events.AutopsyEventException; import org.sleuthkit.autopsy.events.AutopsyEventPublisher; @@ -1016,7 +1017,7 @@ public class Case { public String getModuleOutputDirectoryRelativePath() { Path thePath; if (getCaseType() == CaseType.MULTI_USER_CASE) { - thePath = Paths.get(getLocalHostName(), MODULE_FOLDER); + thePath = Paths.get(NetworkUtils.getLocalHostName(), MODULE_FOLDER); } else { thePath = Paths.get(MODULE_FOLDER); } @@ -1029,7 +1030,7 @@ public class Case { * Get the host output directory path where modules should save their * permanent data. If single-user case, the directory is a subdirectory of * the case directory. If multi-user case, the directory is a subdirectory - * of HostName, which is a subdirectory of the case directory. + * of the hostName, which is a subdirectory of the case directory. * * @return the path to the host output directory */ @@ -1037,7 +1038,7 @@ public class Case { String caseDirectory = getCaseDirectory(); Path hostPath; if (caseType == CaseType.MULTI_USER_CASE) { - hostPath = Paths.get(caseDirectory, getLocalHostName()); + hostPath = Paths.get(caseDirectory, NetworkUtils.getLocalHostName()); } else { hostPath = Paths.get(caseDirectory); } @@ -1353,7 +1354,7 @@ public class Case { String hostClause = ""; if (caseType == CaseType.MULTI_USER_CASE) { - hostClause = File.separator + getLocalHostName(); + hostClause = File.separator + NetworkUtils.getLocalHostName(); } result = result && (new File(caseDir + hostClause + File.separator + EXPORT_FOLDER)).mkdirs() && (new File(caseDir + hostClause + File.separator + LOG_FOLDER)).mkdirs() @@ -1568,24 +1569,5 @@ public class Case { return hasData; } - /** - * Set the host name variable. Sometimes the network can be finicky, so the - * answer returned by getHostName() could throw an exception or be null. - * Have it read the environment variable if getHostName() is unsuccessful. - */ - public static String getLocalHostName() { - if (HostName == null || HostName.isEmpty()) { - try { - HostName = java.net.InetAddress.getLocalHost().getHostName(); - } catch (UnknownHostException ex) { - // getLocalHost().getHostName() can fail in some situations. - // Use environment variable if so. - HostName = System.getenv("COMPUTERNAME"); - } - if (HostName == null || HostName.isEmpty()) { - HostName = System.getenv("COMPUTERNAME"); - } - } - return HostName; - } + } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CollaborationMonitor.java b/Core/src/org/sleuthkit/autopsy/casemodule/CollaborationMonitor.java index 254d404c4e..16dfde423d 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CollaborationMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CollaborationMonitor.java @@ -48,6 +48,7 @@ import org.sleuthkit.autopsy.casemodule.events.DataSourceAddedEvent; import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; +import org.sleuthkit.autopsy.coreutils.NetworkUtils; import org.sleuthkit.autopsy.events.AutopsyEvent; import org.sleuthkit.autopsy.events.AutopsyEventException; import org.sleuthkit.autopsy.events.AutopsyEventPublisher; @@ -95,7 +96,7 @@ final class CollaborationMonitor { * Get the local host name so it can be used to identify the source of * collaboration tasks broadcast by this node. */ - hostName = getHostName(); + hostName = NetworkUtils.getLocalHostName(); /** * Create an event publisher that will be used to communicate with @@ -137,24 +138,6 @@ final class CollaborationMonitor { periodicTasksExecutor.scheduleAtFixedRate(new CrashDetectionTask(), CRASH_DETECTION_INTERVAL_MINUTES, CRASH_DETECTION_INTERVAL_MINUTES, TimeUnit.MINUTES); } - /** - * Determines the name of the local host for use in describing local tasks. - * - * @return The host name of this Autopsy node. - */ - private static String getHostName() { - String name; - try { - name = java.net.InetAddress.getLocalHost().getHostName(); - } catch (UnknownHostException notUsed) { - name = System.getenv("COMPUTERNAME"); - } - if (name.isEmpty()) { - name = "Collaborator"; - } - return name; - } - /** * Shuts down this collaboration monitor. */ diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseConverter.java b/Core/src/org/sleuthkit/autopsy/casemodule/SingleUserCaseImporter.java similarity index 93% rename from Core/src/org/sleuthkit/autopsy/casemodule/CaseConverter.java rename to Core/src/org/sleuthkit/autopsy/casemodule/SingleUserCaseImporter.java index 9c27afe5ab..7a8c38a7de 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseConverter.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/SingleUserCaseImporter.java @@ -45,23 +45,25 @@ import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case.CaseType; import org.sleuthkit.datamodel.CaseDbConnectionInfo; import org.sleuthkit.datamodel.SleuthkitCase; +import org.sleuthkit.autopsy.coreutils.NetworkUtils; +import org.sleuthkit.autopsy.coreutils.TimeStampUtils; /** * Convert case(s) from single-user to multi-user. Recursively scans subfolders. */ -public class CaseConverter implements Runnable { +public class SingleUserCaseImporter implements Runnable { private static final String AUTOPSY_DB_FILE = "autopsy.db"; //NON-NLS private static final String DOTAUT = ".aut"; //NON-NLS - private static final String CACHE_FOLDER = "Cache"; //NON-NLS - private static final String EXPORT_FOLDER = "Export"; //NON-NLS - private static final String LOG_FOLDER = "Log"; //NON-NLS - private static final String MODULE_FOLDER = "ModuleOutput"; //NON-NLS - private static final String REPORTS_FOLDER = "Reports"; //NON-NLS - private static final String TEMP_FOLDER = "Temp"; //NON-NLS - private static final String TIMELINE_FOLDER = "Timeline"; //NON-NLS - private final static String AIM_LOG_FILE_NAME = "auto_ingest_log.txt"; //NON-NLS - private final static String TIMELINE_FILE = "events.db"; //NON-NLS + //private static final String CACHE_FOLDER = "Cache"; //NON-NLS + //private static final String EXPORT_FOLDER = "Export"; //NON-NLS + //private static final String LOG_FOLDER = "Log"; //NON-NLS + //private static final String MODULE_FOLDER = "ModuleOutput"; //NON-NLS + //private static final String REPORTS_FOLDER = "Reports"; //NON-NLS + //private static final String TEMP_FOLDER = "Temp"; //NON-NLS + //private static final String TIMELINE_FOLDER = "Timeline"; //NON-NLS + //private final static String AIM_LOG_FILE_NAME = "auto_ingest_log.txt"; //NON-NLS + //private final static String TIMELINE_FILE = "events.db"; //NON-NLS public static final String CASE_CONVERSION_LOG_FILE = "case_conversion.txt"; //NON-NLS private static final String logDateFormat = "yyyy/MM/dd HH:mm:ss"; //NON-NLS private static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(logDateFormat); @@ -89,7 +91,7 @@ public class CaseConverter implements Runnable { * @param callback a callback from the calling panel for notification when * the conversion has completed. This is a Runnable on a different thread. */ - public CaseConverter(String caseInput, String caseOutput, String imageInput, String imageOutput, CaseDbConnectionInfo database, ConversionDoneCallback callback) { + public SingleUserCaseImporter(String caseInput, String caseOutput, String imageInput, String imageOutput, CaseDbConnectionInfo database, ConversionDoneCallback callback) { this.caseInputFolder = caseInput; this.caseOutputFolder = caseOutput; this.imageInputFolder = imageInput; @@ -127,7 +129,7 @@ public class CaseConverter implements Runnable { // read old xml config oldXmlCaseManagement.open(input.resolve(oldCaseName + DOTAUT).toString()); if (oldXmlCaseManagement.getCaseType() == CaseType.MULTI_USER_CASE) { - throw new Exception(NbBundle.getMessage(CaseConverter.class, "CaseConverter.AlreadyMultiUser")); + throw new Exception(NbBundle.getMessage(SingleUserCaseImporter.class, "CaseConverter.AlreadyMultiUser")); } String newCaseFolder = prepareOutput(caseOutputFolder, oldCaseFolder); @@ -144,7 +146,7 @@ public class CaseConverter implements Runnable { File imageDestination = Paths.get(imageOutputFolder, caseName).toFile(); - copyResults(input, newCaseFolder); // Copy items to new hostname folder structure + copyResults(input, newCaseFolder, oldCaseName); // Copy items to new hostname folder structure dbName = convertDb(dbName, input, newCaseFolder); // Change from SQLite to PostgreSQL File imageSource = copyInputImages(imageInputFolder, oldCaseName, imageDestination); // Copy images over fixPaths(imageSource.toString(), imageDestination.toString(), dbName); // Update paths in DB @@ -159,8 +161,8 @@ public class CaseConverter implements Runnable { // Set created date. This calls writefile, no need to call it again newXmlCaseManagement.setCreatedDate(oldXmlCaseManagement.getCreatedDate()); - log(NbBundle.getMessage(CaseConverter.class, "CaseConverter.FinishedConverting") - + input.toString() + NbBundle.getMessage(CaseConverter.class, "CaseConverter.To") + log(NbBundle.getMessage(SingleUserCaseImporter.class, "CaseConverter.FinishedConverting") + + input.toString() + NbBundle.getMessage(SingleUserCaseImporter.class, "CaseConverter.To") + caseOutputFolder + File.separatorChar + newCaseFolder); } catch (Exception exp) { /// clean up here @@ -179,13 +181,13 @@ public class CaseConverter implements Runnable { */ private void checkInput(File caseInput, File imageInput) throws Exception { if (false == caseInput.exists()) { - throw new Exception(NbBundle.getMessage(CaseConverter.class, "CaseConverter.BadCaseSourceFolder")); + throw new Exception(NbBundle.getMessage(SingleUserCaseImporter.class, "CaseConverter.BadCaseSourceFolder")); } else if (false == imageInput.exists()) { - throw new Exception(NbBundle.getMessage(CaseConverter.class, "CaseConverter.BadImageSourceFolder")); + throw new Exception(NbBundle.getMessage(SingleUserCaseImporter.class, "CaseConverter.BadImageSourceFolder")); } Path path = Paths.get(caseInput.toString(), AUTOPSY_DB_FILE); if (false == path.toFile().exists()) { - throw new Exception(NbBundle.getMessage(CaseConverter.class, "CaseConverter.BadDatabaseFileName")); + throw new Exception(NbBundle.getMessage(SingleUserCaseImporter.class, "CaseConverter.BadDatabaseFileName")); } } @@ -213,7 +215,7 @@ public class CaseConverter implements Runnable { while (specificOutputFolder.exists()) { if (number == Integer.MAX_VALUE) { // oops. it never became unique. give up. - throw new Exception(NbBundle.getMessage(CaseConverter.class, "CaseConverter.NonUniqueOutputFolder") + caseFolder); + throw new Exception(NbBundle.getMessage(SingleUserCaseImporter.class, "CaseConverter.NonUniqueOutputFolder") + caseFolder); } temp = sanitizedCaseName + "_" + Integer.toString(number) + timeStamp; //NON-NLS specificOutputFolder = Paths.get(caseOutputFolder, temp).toFile(); @@ -235,9 +237,27 @@ public class CaseConverter implements Runnable { * @param newCaseFolder deconflicted case name for the new multi-user case * @throws IOException */ - private void copyResults(Path input, String newCaseFolder) throws IOException { + private void copyResults(Path input, String newCaseFolder, String caseName) throws IOException { /// get hostname - String hostName = Case.getLocalHostName(); + String hostName = NetworkUtils.getLocalHostName(); + + if(input.toFile().exists()){ + Path destination = Paths.get(caseOutputFolder, newCaseFolder, hostName); + FileUtils.copyDirectory(input.toFile(), destination.toFile()); + } + + // Remove the single-user .aut file and database + File oldDatabaseFile = Paths.get(caseOutputFolder, newCaseFolder, hostName, caseName + ".aut").toFile(); + if(oldDatabaseFile.exists()){ + oldDatabaseFile.delete(); + } + + File oldAutopsyFile = Paths.get(caseOutputFolder, newCaseFolder, hostName, "autopsy.db").toFile(); + if(oldAutopsyFile.exists()){ + oldAutopsyFile.delete(); + } + + /* Path source = input.resolve(CACHE_FOLDER); Path destination; @@ -287,11 +307,11 @@ public class CaseConverter implements Runnable { destination = Paths.get(caseOutputFolder, newCaseFolder, AIM_LOG_FILE_NAME); FileUtils.copyFile(source.toFile(), destination.toFile()); try (PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(destination.toString(), true)))) { - out.println(NbBundle.getMessage(CaseConverter.class, "CaseConverter.ConvertedToMultiUser") + new Date()); + out.println(NbBundle.getMessage(SingleUserCaseImporter.class, "SingleUserCaseImporter.ConvertedToMultiUser") + new Date()); } catch (IOException e) { // if unable to log it, no problem } - } + }*/ } /** @@ -944,7 +964,7 @@ public class CaseConverter implements Runnable { // not unique. add numbers before dbName. if (number == Integer.MAX_VALUE) { // oops. it never became unique. give up. - throw new Exception(NbBundle.getMessage(CaseConverter.class, "CaseConverter.NonUniqueDatabaseName")); + throw new Exception(NbBundle.getMessage(SingleUserCaseImporter.class, "CaseConverter.NonUniqueDatabaseName")); } sanitizedDbName = "_" + Integer.toString(number) + "_" + baseDbName; //NON-NLS @@ -959,7 +979,7 @@ public class CaseConverter implements Runnable { } else { // Could be caused by database credentials, using user accounts that // can not check if other databases exist, so allow it to continue - log(NbBundle.getMessage(CaseConverter.class, "CaseConverter.PotentiallyNonUniqueDatabaseName")); + log(NbBundle.getMessage(SingleUserCaseImporter.class, "CaseConverter.PotentiallyNonUniqueDatabaseName")); } return sanitizedDbName; @@ -992,7 +1012,7 @@ public class CaseConverter implements Runnable { if (chosenInput != null && chosenInput.exists()) { FileUtils.copyDirectory(chosenInput, output); } else { - log(NbBundle.getMessage(CaseConverter.class, "CaseConverter.UnableToCopySourceImages")); + log(NbBundle.getMessage(SingleUserCaseImporter.class, "CaseConverter.UnableToCopySourceImages")); } return chosenInput; } @@ -1005,7 +1025,7 @@ public class CaseConverter implements Runnable { /// Fix paths in reports, tsk_files_path, and tsk_image_names tables Connection postgresqlConnection = DriverManager.getConnection("jdbc:postgresql://" + db.getHost() + ":" + db.getPort() + "/" + dbName, db.getUserName(), db.getPassword()); //NON-NLS - String hostName = Case.getLocalHostName(); + String hostName = NetworkUtils.getLocalHostName(); // add hostname to reports Statement updateStatement = postgresqlConnection.createStatement(); @@ -1180,11 +1200,11 @@ public class CaseConverter implements Runnable { * not. True if all was successful, false otherwise. */ private void closeLog(boolean result) { - log(NbBundle.getMessage(CaseConverter.class, "CaseConverter.FinishedConverting") + log(NbBundle.getMessage(SingleUserCaseImporter.class, "CaseConverter.FinishedConverting") + caseInputFolder - + NbBundle.getMessage(CaseConverter.class, "CaseConverter.To") + + NbBundle.getMessage(SingleUserCaseImporter.class, "CaseConverter.To") + caseOutputFolder - + NbBundle.getMessage(CaseConverter.class, "CaseConverter.ConversionSuccessful") + + NbBundle.getMessage(SingleUserCaseImporter.class, "CaseConverter.ConversionSuccessful") + result); if (writer != null) { diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/XMLCaseManagement.java b/Core/src/org/sleuthkit/autopsy/casemodule/XMLCaseManagement.java index eec16fd912..0f22f74f97 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/XMLCaseManagement.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/XMLCaseManagement.java @@ -45,7 +45,7 @@ import org.xml.sax.SAXException; * * @author jantonius */ -public class XMLCaseManagement implements CaseConfigFileInterface { +class XMLCaseManagement implements CaseConfigFileInterface { final static String XSDFILE = "CaseSchema.xsd"; //NON-NLS final static String TOP_ROOT_NAME = "AutopsyCase"; //NON-NLS diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/NetworkUtils.java b/Core/src/org/sleuthkit/autopsy/coreutils/NetworkUtils.java new file mode 100644 index 0000000000..87e7dfad5f --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/coreutils/NetworkUtils.java @@ -0,0 +1,43 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2012-2015 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.coreutils; + +import java.net.UnknownHostException; + +public class NetworkUtils { + /** + * Set the host name variable. Sometimes the network can be finicky, so the + * answer returned by getHostName() could throw an exception or be null. + * Have it read the environment variable if getHostName() is unsuccessful. + */ + public static String getLocalHostName() { + String hostName = ""; + try { + hostName = java.net.InetAddress.getLocalHost().getHostName(); + } catch (UnknownHostException ex) { + // getLocalHost().getHostName() can fail in some situations. + // Use environment variable if so. + hostName = System.getenv("COMPUTERNAME"); + } + if (hostName == null || hostName.isEmpty()) { + hostName = System.getenv("COMPUTERNAME"); + } + return hostName; + } +} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/TimeStampUtils.java b/Core/src/org/sleuthkit/autopsy/coreutils/TimeStampUtils.java similarity index 87% rename from Core/src/org/sleuthkit/autopsy/casemodule/TimeStampUtils.java rename to Core/src/org/sleuthkit/autopsy/coreutils/TimeStampUtils.java index c7337fa2f0..0b95bb932d 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/TimeStampUtils.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/TimeStampUtils.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.casemodule; +package org.sleuthkit.autopsy.coreutils; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -26,8 +26,8 @@ import java.util.regex.Pattern; */ public final class TimeStampUtils { - // Pattern to identify whether case name contains a time stamp generated by Auto Ingest. - // Sample case name created by auto-ingest: Case 1_2015_02_02_12_10_31 for case "Case 1" + // Pattern to identify whether case name contains a generated time stamp. + // Sample case name with time stamp: Case 1_2015_02_02_12_10_31 for case "Case 1" private static final Pattern timeStampPattern = Pattern.compile("\\d{4}_\\d{2}_\\d{2}_\\d{2}_\\d{2}_\\d{2}$"); private static final int LENGTH_OF_DATE_TIME_STAMP = 20; // length of the above time stamp diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/TimestampingFormatter.java b/Core/src/org/sleuthkit/autopsy/coreutils/TimestampingFormatter.java deleted file mode 100644 index 77d2c269cd..0000000000 --- a/Core/src/org/sleuthkit/autopsy/coreutils/TimestampingFormatter.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2011 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.coreutils; - -import java.text.DateFormat; -import java.util.Date; -import java.util.Locale; -import java.util.logging.Formatter; -import java.util.logging.LogRecord; - -/* - * Formatter to wrap another formatter and prepend a timestampe to each formatted string - * Not currently used. - */ - class TimestampingFormatter extends Formatter { - - Formatter original; - DateFormat timestampFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, Locale.US); - String lineSeparator = System.getProperty("line.separator"); - - TimestampingFormatter(Formatter original) { - this.original = original; - } - - @Override - public String format(LogRecord record) { - long millis = record.getMillis(); - String timestamp = timestampFormat.format(new Date(millis)); - - return timestamp + lineSeparator + original.format(record); - } -} From 64ea31b14bca45ff7c9f2594773b400d423749fb Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Thu, 23 Jul 2015 09:42:09 -0400 Subject: [PATCH 2/3] Added copy image and delete options to SingleUserCaseImporter --- .../autopsy/casemodule/Bundle.properties | 3 +- .../casemodule/SingleUserCaseImporter.java | 107 ++++++------------ 2 files changed, 36 insertions(+), 74 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties index 37f01bbb60..784d7c4d8a 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties @@ -263,4 +263,5 @@ CaseConverter.NonUniqueDatabaseName=Database name not unique. Skipping. CaseConverter.PotentiallyNonUniqueDatabaseName=Unclear if database name unique. Moving ahead. CaseConverter.ConvertedToMultiUser=This case was converted to a Multi-user collaborative case on CaseConverter.UnableToCopySourceImages=Unable to copy source images -CaseConverter.ConversionSuccessful=. Conversion successful: \ No newline at end of file +CaseConverter.ConversionSuccessful=. Conversion successful: +CaseConverter.DeletingCase=Deleting original case folder \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/SingleUserCaseImporter.java b/Core/src/org/sleuthkit/autopsy/casemodule/SingleUserCaseImporter.java index 7a8c38a7de..fe946f121a 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/SingleUserCaseImporter.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/SingleUserCaseImporter.java @@ -39,10 +39,12 @@ import java.text.SimpleDateFormat; import java.time.Instant; import java.util.ArrayList; import java.util.Date; +import java.util.logging.Level; import org.apache.commons.io.FileUtils; import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case.CaseType; +import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.CaseDbConnectionInfo; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.autopsy.coreutils.NetworkUtils; @@ -55,16 +57,7 @@ public class SingleUserCaseImporter implements Runnable { private static final String AUTOPSY_DB_FILE = "autopsy.db"; //NON-NLS private static final String DOTAUT = ".aut"; //NON-NLS - //private static final String CACHE_FOLDER = "Cache"; //NON-NLS - //private static final String EXPORT_FOLDER = "Export"; //NON-NLS - //private static final String LOG_FOLDER = "Log"; //NON-NLS - //private static final String MODULE_FOLDER = "ModuleOutput"; //NON-NLS - //private static final String REPORTS_FOLDER = "Reports"; //NON-NLS - //private static final String TEMP_FOLDER = "Temp"; //NON-NLS - //private static final String TIMELINE_FOLDER = "Timeline"; //NON-NLS - //private final static String AIM_LOG_FILE_NAME = "auto_ingest_log.txt"; //NON-NLS - //private final static String TIMELINE_FILE = "events.db"; //NON-NLS - public static final String CASE_CONVERSION_LOG_FILE = "case_conversion.txt"; //NON-NLS + public static final String CASE_CONVERSION_LOG_FILE = "case_import_log.txt"; //NON-NLS private static final String logDateFormat = "yyyy/MM/dd HH:mm:ss"; //NON-NLS private static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(logDateFormat); private static final int MAX_DB_NAME_LENGTH = 63; @@ -73,6 +66,8 @@ public class SingleUserCaseImporter implements Runnable { private final String caseOutputFolder; private final String imageInputFolder; private final String imageOutputFolder; + private final boolean copyImages; + private final boolean deleteCase; private final CaseDbConnectionInfo db; private final ConversionDoneCallback notifyOnComplete; private PrintWriter writer; @@ -88,14 +83,19 @@ public class SingleUserCaseImporter implements Runnable { * @param imageInput the folder that holds the images to copy over * @param imageOutput the destination folder for the images * @param database the connection information to talk to the PostgreSQL db + * @param copyImages true if images should be copied + * @param deleteCase true if the old version of the case should be deleted after import * @param callback a callback from the calling panel for notification when * the conversion has completed. This is a Runnable on a different thread. */ - public SingleUserCaseImporter(String caseInput, String caseOutput, String imageInput, String imageOutput, CaseDbConnectionInfo database, ConversionDoneCallback callback) { + public SingleUserCaseImporter(String caseInput, String caseOutput, String imageInput, String imageOutput, CaseDbConnectionInfo database, + boolean copyImages, boolean deleteCase, ConversionDoneCallback callback) { this.caseInputFolder = caseInput; this.caseOutputFolder = caseOutput; this.imageInputFolder = imageInput; this.imageOutputFolder = imageOutput; + this.copyImages = copyImages; + this.deleteCase = deleteCase; this.db = database; this.notifyOnComplete = callback; } @@ -117,7 +117,12 @@ public class SingleUserCaseImporter implements Runnable { try { log("Beginning to convert " + input.toString() + " to " + caseOutputFolder + "\\" + oldCaseFolder); //NON-NLS - checkInput(input.toFile(), new File(imageInputFolder)); + if(copyImages){ + checkInput(input.toFile(), new File(imageInputFolder)); + } + else{ + checkInput(input.toFile(), null); + } String oldCaseName = oldCaseFolder; if (TimeStampUtils.endsWithTimeStamp(oldCaseName)) { oldCaseName = oldCaseName.substring(0, oldCaseName.length() - TimeStampUtils.getTimeStampLength()); @@ -148,8 +153,10 @@ public class SingleUserCaseImporter implements Runnable { copyResults(input, newCaseFolder, oldCaseName); // Copy items to new hostname folder structure dbName = convertDb(dbName, input, newCaseFolder); // Change from SQLite to PostgreSQL - File imageSource = copyInputImages(imageInputFolder, oldCaseName, imageDestination); // Copy images over - fixPaths(imageSource.toString(), imageDestination.toString(), dbName); // Update paths in DB + if(copyImages){ + File imageSource = copyInputImages(imageInputFolder, oldCaseName, imageDestination); // Copy images over + fixPaths(imageSource.toString(), imageDestination.toString(), dbName); // Update paths in DB + } // create new XML config newXmlCaseManagement.create(Paths.get(caseOutputFolder, newCaseFolder).toString(), @@ -161,6 +168,15 @@ public class SingleUserCaseImporter implements Runnable { // Set created date. This calls writefile, no need to call it again newXmlCaseManagement.setCreatedDate(oldXmlCaseManagement.getCreatedDate()); + // At this point the import has been finished successfully so we can delete the original case + // (if requested). This *should* be fairly safe - at this point we know there was an autopsy file + // and database in the given directory so the user shouldn't be able to accidently blow away + // their C drive. + if(deleteCase){ + log(NbBundle.getMessage(SingleUserCaseImporter.class, "CaseConverter.DeletingCase") + " " + input); + FileUtils.deleteDirectory(input.toFile()); + } + log(NbBundle.getMessage(SingleUserCaseImporter.class, "CaseConverter.FinishedConverting") + input.toString() + NbBundle.getMessage(SingleUserCaseImporter.class, "CaseConverter.To") + caseOutputFolder + File.separatorChar + newCaseFolder); @@ -176,13 +192,13 @@ public class SingleUserCaseImporter implements Runnable { * Ensure the input source has an autopsy.db and exists. * * @param caseInput The folder containing a case to convert. - * @param imageInput The folder containing the images to copy. + * @param imageInput The folder containing the images to copy or null if images are not being copied. * @throws Exception */ private void checkInput(File caseInput, File imageInput) throws Exception { if (false == caseInput.exists()) { throw new Exception(NbBundle.getMessage(SingleUserCaseImporter.class, "CaseConverter.BadCaseSourceFolder")); - } else if (false == imageInput.exists()) { + } else if ((imageInput != null) && (false == imageInput.exists())) { throw new Exception(NbBundle.getMessage(SingleUserCaseImporter.class, "CaseConverter.BadImageSourceFolder")); } Path path = Paths.get(caseInput.toString(), AUTOPSY_DB_FILE); @@ -256,62 +272,6 @@ public class SingleUserCaseImporter implements Runnable { if(oldAutopsyFile.exists()){ oldAutopsyFile.delete(); } - - /* - Path source = input.resolve(CACHE_FOLDER); - Path destination; - - if (source.toFile().exists()) { - destination = Paths.get(caseOutputFolder, newCaseFolder, hostName, CACHE_FOLDER); - FileUtils.copyDirectory(source.toFile(), destination.toFile()); - } - - source = input.resolve(EXPORT_FOLDER); - if (source.toFile().exists()) { - destination = Paths.get(caseOutputFolder, newCaseFolder, hostName, EXPORT_FOLDER); - FileUtils.copyDirectory(source.toFile(), destination.toFile()); - } - - source = input.resolve(LOG_FOLDER); - if (source.toFile().exists()) { - destination = Paths.get(caseOutputFolder, newCaseFolder, hostName, LOG_FOLDER); - FileUtils.copyDirectory(source.toFile(), destination.toFile()); - } - - source = input.resolve(MODULE_FOLDER); - if (source.toFile().exists()) { - destination = Paths.get(caseOutputFolder, newCaseFolder, hostName, MODULE_FOLDER); - FileUtils.copyDirectory(source.toFile(), destination.toFile()); - } - - source = input.resolve(REPORTS_FOLDER); - if (source.toFile().exists()) { - destination = Paths.get(caseOutputFolder, newCaseFolder, hostName, REPORTS_FOLDER); - FileUtils.copyDirectory(source.toFile(), destination.toFile()); - } - - source = input.resolve(TEMP_FOLDER); - if (source.toFile().exists()) { - destination = Paths.get(caseOutputFolder, newCaseFolder, hostName, TEMP_FOLDER); - FileUtils.copyDirectory(source.toFile(), destination.toFile()); - } - - source = input.resolve(TIMELINE_FILE); - if (source.toFile().exists()) { - destination = Paths.get(caseOutputFolder, newCaseFolder, hostName, MODULE_FOLDER, TIMELINE_FOLDER, TIMELINE_FILE); - FileUtils.copyFile(source.toFile(), destination.toFile()); - } - - source = input.resolve(AIM_LOG_FILE_NAME); - if (source.toFile().exists()) { - destination = Paths.get(caseOutputFolder, newCaseFolder, AIM_LOG_FILE_NAME); - FileUtils.copyFile(source.toFile(), destination.toFile()); - try (PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(destination.toString(), true)))) { - out.println(NbBundle.getMessage(SingleUserCaseImporter.class, "SingleUserCaseImporter.ConvertedToMultiUser") + new Date()); - } catch (IOException e) { - // if unable to log it, no problem - } - }*/ } /** @@ -924,6 +884,7 @@ public class SingleUserCaseImporter implements Runnable { numberingPK = postgresqlConnection.createStatement(); numberingPK.execute("ALTER SEQUENCE blackboard_artifact_tags_tag_id_seq RESTART WITH " + (biggestPK + 1)); //NON-NLS + sqliteConnection.close(); postgresqlConnection.close(); return dbName; @@ -1177,7 +1138,7 @@ public class SingleUserCaseImporter implements Runnable { writer = new PrintWriter(new BufferedWriter(new FileWriter(logFile, logFile.exists())), true); } catch (IOException ex) { writer = null; - Exceptions.printStackTrace(ex); + Logger.getLogger(SingleUserCaseImporter.class.getName()).log(Level.WARNING, "Error opening log file " + logFile.toString(), ex); } } From 8378ff9bd4c437f37dc7791079b7c2dc03ab1d49 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Thu, 23 Jul 2015 09:59:14 -0400 Subject: [PATCH 3/3] Reverting bundle properties --- .../core.jar/org/netbeans/core/startup/Bundle.properties | 4 ++-- .../org/netbeans/core/windows/view/ui/Bundle.properties | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties index 84e42eab37..54a8353a13 100644 --- a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties +++ b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties @@ -1,5 +1,5 @@ #Updated by build script -#Thu, 23 Jul 2015 09:29:40 -0400 +#Thu, 25 Jun 2015 13:09:21 -0400 LBL_splash_window_title=Starting Autopsy SPLASH_HEIGHT=314 SPLASH_WIDTH=538 @@ -8,4 +8,4 @@ SplashRunningTextBounds=0,289,538,18 SplashRunningTextColor=0x0 SplashRunningTextFontSize=19 -currentVersion=Autopsy 3.1.3 +currentVersion=Autopsy 3.1.2 diff --git a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties index 122b976d9e..3b8f688ddc 100644 --- a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties +++ b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties @@ -1,5 +1,5 @@ #Updated by build script -#Thu, 23 Jul 2015 09:29:40 -0400 +#Thu, 25 Jun 2015 13:09:21 -0400 -CTL_MainWindow_Title=Autopsy 3.1.3 -CTL_MainWindow_Title_No_Project=Autopsy 3.1.3 +CTL_MainWindow_Title=Autopsy 3.1.2 +CTL_MainWindow_Title_No_Project=Autopsy 3.1.2