diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index cd984c2155..cf5a02a0e4 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -662,6 +662,18 @@ public class Case implements SleuthkitCase.ErrorObserver { public String getTextIndexName() { return getCaseMetadata().getTextIndexName(); } + + /** + * Sets the name of the keyword search index for the case. + * + * @param indexName The index name. + * + * @throws + * org.sleuthkit.autopsy.casemodule.CaseMetadata.CaseMetadataException + */ + public void setTextIndexName(String indexName) throws CaseMetadataException { + caseMetadata.setTextIndexName(indexName); + } /** * Queries whether or not the case has data, i.e., whether or not at least @@ -984,19 +996,17 @@ public class Case implements SleuthkitCase.ErrorObserver { } /* - * Sanitize the case name, create a unique keyword search index name, - * and create a standard (single-user) or unique (multi-user) case - * database name. + * Sanitize the case name, and create a standard (single-user) or + * unique (multi-user) case database name. */ String santizedCaseName = sanitizeCaseName(caseName); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss"); Date date = new Date(); - String indexName = santizedCaseName + "_" + dateFormat.format(date); String dbName = null; if (caseType == CaseType.SINGLE_USER_CASE) { dbName = caseDir + File.separator + "autopsy.db"; //NON-NLS } else if (caseType == CaseType.MULTI_USER_CASE) { - dbName = indexName; + dbName = santizedCaseName + "_" + dateFormat.format(date); } try{ @@ -1037,7 +1047,7 @@ public class Case implements SleuthkitCase.ErrorObserver { */ CaseMetadata metadata; try { - metadata = new CaseMetadata(caseDir, caseType, caseName, caseNumber, examiner, dbName, indexName); + metadata = new CaseMetadata(caseDir, caseType, caseName, caseNumber, examiner, dbName); } catch (CaseMetadataException ex) { throw new CaseActionException(Bundle.Case_creationException(), ex); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java index bd07a3deaf..19e62db1d2 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java @@ -102,19 +102,17 @@ public final class CaseMetadata { * @param caseDatabase For a single-user case, the full path to the * case database file. For a multi-user case, the * case database name. - * @param caseTextIndexName The text index name. * * @throws CaseMetadataException If the new case metadata file cannot be * created. */ - CaseMetadata(String caseDirectory, Case.CaseType caseType, String caseName, String caseNumber, String examiner, String caseDatabase, String caseTextIndexName) throws CaseMetadataException { + CaseMetadata(String caseDirectory, Case.CaseType caseType, String caseName, String caseNumber, String examiner, String caseDatabase) throws CaseMetadataException { metadataFilePath = Paths.get(caseDirectory, caseName + FILE_EXTENSION); this.caseType = caseType; this.caseName = caseName; this.caseNumber = caseNumber; this.examiner = examiner; this.caseDatabase = caseDatabase; - this.textIndexName = caseTextIndexName; createdByVersion = Version.getVersion(); createdDate = CaseMetadata.DATE_FORMAT.format(new Date()); writeToFile(); @@ -186,6 +184,22 @@ public final class CaseMetadata { throw ex; } } + + /** + * Sets the text index name. + * + * @param caseTextIndexName The text index name. + */ + void setTextIndexName(String caseTextIndexName) throws CaseMetadataException { + String oldIndexName = caseTextIndexName; + this.textIndexName = caseTextIndexName; + try { + writeToFile(); + } catch (CaseMetadataException ex) { + this.textIndexName = oldIndexName; + throw ex; + } + } /** * Gets the case number. diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/SingleUserCaseConverter.java b/Core/src/org/sleuthkit/autopsy/casemodule/SingleUserCaseConverter.java index e39f0d5ebb..31e655838d 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/SingleUserCaseConverter.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/SingleUserCaseConverter.java @@ -176,7 +176,6 @@ public class SingleUserCaseConverter { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss"); //NON-NLS Date date = new Date(); String dbName = Case.sanitizeCaseName(icd.getNewCaseName()) + "_" + dateFormat.format(date); //NON-NLS - String solrName = dbName; icd.setPostgreSQLDbName(dbName); // Copy items to new hostname folder structure @@ -197,7 +196,7 @@ public class SingleUserCaseConverter { icd.getNewCaseName(), oldCaseMetadata.getCaseNumber(), oldCaseMetadata.getExaminer(), - dbName, solrName); + dbName); // Set created date. This calls writefile, no need to call it again newCaseMetadata.setCreatedDate(oldCaseMetadata.getCreatedDate()); newCaseMetadata.setCreatedByVersion(oldCaseMetadata.getCreatedByVersion()); diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java index acc8e4d2d3..c35bd01117 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java @@ -65,6 +65,7 @@ import org.openide.modules.Places; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case.CaseType; +import org.sleuthkit.autopsy.casemodule.CaseMetadata; import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ModuleSettings; @@ -742,15 +743,7 @@ public class Server { } try { - CaseType caseType = theCase.getCaseType(); - String coreName; - if (index.isNewIndex()) { - // come up with a new core name - coreName = createCoreName(theCase.getName()); - } else { - // ELTODO get core name - coreName = ""; - } + String coreName = getCoreName(index, theCase); File dataDir = new File(new File(index.getIndexPath()).getParent()); // "data dir" is the parent of the index directory if (!dataDir.exists()) { @@ -771,7 +764,7 @@ public class Server { // In single user mode, if there is a core.properties file already, // we've hit a solr bug. Compensate by deleting it. - if (caseType == CaseType.SINGLE_USER_CASE) { + if (theCase.getCaseType() == CaseType.SINGLE_USER_CASE) { Path corePropertiesFile = Paths.get(solrFolder.toString(), SOLR, coreName, CORE_PROPERTIES); if (corePropertiesFile.toFile().exists()) { try { @@ -795,13 +788,48 @@ public class Server { throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.openCore.exception.noIndexDir.msg")); } - return new Core(coreName, caseType, index); + return new Core(coreName, theCase.getCaseType(), index); - } catch (SolrServerException | SolrException | IOException ex) { + } catch (SolrServerException | SolrException | IOException | CaseMetadata.CaseMetadataException ex) { throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.openCore.exception.cantOpen.msg"), ex); } } + /** + * Get or create a sanitized Solr core name. Stores the core name if needed. + * + * @param index Index object + * @param theCase Case object + * + * @return The sanitized Solr core name + */ + private String getCoreName(Index index, Case theCase) throws CaseMetadata.CaseMetadataException { + String coreName = ""; + if (index.isNewIndex()) { + // come up with a new core name + coreName = createCoreName(theCase.getName()); + // store the new core name + theCase.setTextIndexName(coreName); + } else { + // get core name + coreName = theCase.getTextIndexName(); + if (coreName.isEmpty()) { + // come up with a new core name + coreName = createCoreName(theCase.getName()); + // store the new core name + theCase.setTextIndexName(coreName); + } + } + return coreName; + } + + /** + * Create and sanitize a core name. + * + * @param caseName Case name + * + * @return The sanitized Solr core name + */ private String createCoreName(String caseName) { if (caseName.isEmpty()) { caseName = DEFAULT_CORE_NAME; @@ -809,7 +837,47 @@ public class Server { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss"); Date date = new Date(); String coreName = caseName + "_" + dateFormat.format(date); - return coreName; + return sanitizeCoreName(coreName); + } + + /** + * Sanitizes the case name for Solr cores. + * + * Solr: + * http://stackoverflow.com/questions/29977519/what-makes-an-invalid-core-name + * may not be / \ : + * Starting Solr6: core names must consist entirely of periods, underscores, hyphens, and alphanumerics as well not start with a hyphen. may not contain space characters. + * + * @param coreName A candidate core name. + * + * @return The sanitized core name. + */ + static private String sanitizeCoreName(String coreName) { + + String result; + + // Remove all non-ASCII characters + result = coreName.replaceAll("[^\\p{ASCII}]", "_"); //NON-NLS + + // Remove all control characters + result = result.replaceAll("[\\p{Cntrl}]", "_"); //NON-NLS + + // Remove spaces / \ : ? ' " + result = result.replaceAll("[ /?:'\"\\\\]", "_"); //NON-NLS + + // Make it all lowercase + result = result.toLowerCase(); + + // Must not start with hyphen + if (result.length() > 0 && !(Character.isLetter(result.codePointAt(0))) && !(result.codePointAt(0) == '-')) { + result = "_" + result; + } + + if (result.isEmpty()) { + result = DEFAULT_CORE_NAME; + } + + return result; } /** diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java index c0bd936368..0d7672950c 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java @@ -196,6 +196,8 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService } // proceed with case open currentVersionIndex = indexToUpgrade; + + currentVersionIndex.setNewIndex(true);// ELTODO remove } else { // index needs to be upgraded to latest supported version of Solr