Autopsy  4.9.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
KeywordSearchIngestModule.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2011-2018 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.keywordsearch;
20 
21 import com.google.common.collect.ImmutableList;
22 import java.io.Reader;
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.concurrent.atomic.AtomicInteger;
27 import java.util.logging.Level;
28 import org.openide.util.Lookup;
29 import org.openide.util.NbBundle;
30 import org.openide.util.NbBundle.Messages;
31 import org.openide.util.lookup.Lookups;
50 import org.sleuthkit.datamodel.AbstractFile;
51 import org.sleuthkit.datamodel.TskData;
52 import org.sleuthkit.datamodel.TskData.FileKnown;
53 
62 @NbBundle.Messages({
63  "# {0} - Reason for not starting Solr", "KeywordSearchIngestModule.init.tryStopSolrMsg={0}<br />Please try stopping Java Solr processes if any exist and restart the application.",
64  "KeywordSearchIngestModule.init.badInitMsg=Keyword search server was not properly initialized, cannot run keyword search ingest.",
65  "SolrConnectionCheck.Port=Invalid port number.",
66  "# {0} - Reason for not connecting to Solr", "KeywordSearchIngestModule.init.exception.errConnToSolr.msg=Error connecting to SOLR server: {0}.",
67  "KeywordSearchIngestModule.startUp.noOpenCore.msg=The index could not be opened or does not exist.",
68  "CannotRunFileTypeDetection=Unable to run file type detection."
69 })
70 public final class KeywordSearchIngestModule implements FileIngestModule {
71 
74  public static final List<String> ARCHIVE_MIME_TYPES
75  = ImmutableList.of(
76  //ignore unstructured binary and compressed data, for which string extraction or unzipper works better
77  "application/x-7z-compressed", //NON-NLS
78  "application/x-ace-compressed", //NON-NLS
79  "application/x-alz-compressed", //NON-NLS
80  "application/x-arj", //NON-NLS
81  "application/vnd.ms-cab-compressed", //NON-NLS
82  "application/x-cfs-compressed", //NON-NLS
83  "application/x-dgc-compressed", //NON-NLS
84  "application/x-apple-diskimage", //NON-NLS
85  "application/x-gca-compressed", //NON-NLS
86  "application/x-dar", //NON-NLS
87  "application/x-lzx", //NON-NLS
88  "application/x-lzh", //NON-NLS
89  "application/x-rar-compressed", //NON-NLS
90  "application/x-stuffit", //NON-NLS
91  "application/x-stuffitx", //NON-NLS
92  "application/x-gtar", //NON-NLS
93  "application/x-archive", //NON-NLS
94  "application/x-executable", //NON-NLS
95  "application/x-gzip", //NON-NLS
96  "application/zip", //NON-NLS
97  "application/x-zoo", //NON-NLS
98  "application/x-cpio", //NON-NLS
99  "application/x-shar", //NON-NLS
100  "application/x-tar", //NON-NLS
101  "application/x-bzip", //NON-NLS
102  "application/x-bzip2", //NON-NLS
103  "application/x-lzip", //NON-NLS
104  "application/x-lzma", //NON-NLS
105  "application/x-lzop", //NON-NLS
106  "application/x-z", //NON-NLS
107  "application/x-compress"); //NON-NLS
108 
112  enum StringsExtractOptions {
113  EXTRACT_UTF16,
114  EXTRACT_UTF8,
115  };
116 
117 
118  enum UpdateFrequency {
119 
120  FAST(20),
121  AVG(10),
122  SLOW(5),
123  SLOWEST(1),
124  NONE(Integer.MAX_VALUE),
125  DEFAULT(5);
126  private final int time;
127 
128  UpdateFrequency(int time) {
129  this.time = time;
130  }
131 
132  int getTime() {
133  return time;
134  }
135  };
136  private static final Logger logger = Logger.getLogger(KeywordSearchIngestModule.class.getName());
137  private final IngestServices services = IngestServices.getInstance();
138  private Ingester ingester = null;
139  private Indexer indexer;
141 //only search images from current ingest, not images previously ingested/indexed
142  //accessed read-only by searcher thread
143 
144  private boolean startedSearching = false;
145  private Lookup stringsExtractionContext;
146  private final KeywordSearchJobSettings settings;
147  private boolean initialized = false;
148  private long jobId;
149  private static final AtomicInteger instanceCount = new AtomicInteger(0); //just used for logging
150  private int instanceNum = 0;
151  private static final IngestModuleReferenceCounter refCounter = new IngestModuleReferenceCounter();
153 
154  private enum IngestStatus {
155 
161  SKIPPED_ERROR_IO
162  };
163  private static final Map<Long, Map<Long, IngestStatus>> ingestStatus = new HashMap<>(); //guarded by itself
164 
173  private static void putIngestStatus(long ingestJobId, long fileId, IngestStatus status) {
174  synchronized (ingestStatus) {
175  Map<Long, IngestStatus> ingestStatusForJob = ingestStatus.get(ingestJobId);
176  if (ingestStatusForJob == null) {
177  ingestStatusForJob = new HashMap<>();
178  ingestStatus.put(ingestJobId, ingestStatusForJob);
179  }
180  ingestStatusForJob.put(fileId, status);
181  ingestStatus.put(ingestJobId, ingestStatusForJob);
182  }
183  }
184 
185  KeywordSearchIngestModule(KeywordSearchJobSettings settings) {
186  this.settings = settings;
187  instanceNum = instanceCount.getAndIncrement();
188  }
189 
195  @Messages({
196  "KeywordSearchIngestModule.startupMessage.failedToGetIndexSchema=Failed to get schema version for text index.",
197  "# {0} - Solr version number", "KeywordSearchIngestModule.startupException.indexSolrVersionNotSupported=Adding text no longer supported for Solr version {0} of the text index.",
198  "# {0} - schema version number", "KeywordSearchIngestModule.startupException.indexSchemaNotSupported=Adding text no longer supported for schema version {0} of the text index.",
199  "KeywordSearchIngestModule.noOpenCase.errMsg=No open case available."
200  })
201  @Override
202  public void startUp(IngestJobContext context) throws IngestModuleException {
203  initialized = false;
204  jobId = context.getJobId();
205 
206  Server server = KeywordSearch.getServer();
207  if (server.coreIsOpen() == false) {
208  throw new IngestModuleException(Bundle.KeywordSearchIngestModule_startUp_noOpenCore_msg());
209  }
210 
211  try {
212  Index indexInfo = server.getIndexInfo();
213  if (!IndexFinder.getCurrentSolrVersion().equals(indexInfo.getSolrVersion())) {
214  throw new IngestModuleException(Bundle.KeywordSearchIngestModule_startupException_indexSolrVersionNotSupported(indexInfo.getSolrVersion()));
215  }
216  if (!indexInfo.isCompatible(IndexFinder.getCurrentSchemaVersion())) {
217  throw new IngestModuleException(Bundle.KeywordSearchIngestModule_startupException_indexSchemaNotSupported(indexInfo.getSchemaVersion()));
218  }
219  } catch (NoOpenCoreException ex) {
220  throw new IngestModuleException(Bundle.KeywordSearchIngestModule_startupMessage_failedToGetIndexSchema(), ex);
221  }
222 
223  try {
224  fileTypeDetector = new FileTypeDetector();
226  throw new IngestModuleException(Bundle.CannotRunFileTypeDetection(), ex);
227  }
228 
229  ingester = Ingester.getDefault();
230  this.context = context;
231 
232  // increment the module reference count
233  // if first instance of this module for this job then check the server and existence of keywords
234  Case openCase;
235  try {
236  openCase = Case.getCurrentCaseThrows();
237  } catch (NoCurrentCaseException ex) {
238  throw new IngestModuleException(Bundle.KeywordSearchIngestModule_noOpenCase_errMsg(), ex);
239  }
240  if (refCounter.incrementAndGet(jobId) == 1) {
241  if (openCase.getCaseType() == Case.CaseType.MULTI_USER_CASE) {
242  // for multi-user cases need to verify connection to remore SOLR server
243  KeywordSearchService kwsService = new SolrSearchService();
245  int port;
246  try {
247  port = Integer.parseInt(properties.getPort());
248  } catch (NumberFormatException ex) {
249  // if there is an error parsing the port number
250  throw new IngestModuleException(Bundle.KeywordSearchIngestModule_init_badInitMsg() + " " + Bundle.SolrConnectionCheck_Port(), ex);
251  }
252  try {
253  kwsService.tryConnect(properties.getHost(), port);
254  } catch (KeywordSearchServiceException ex) {
255  throw new IngestModuleException(Bundle.KeywordSearchIngestModule_init_badInitMsg(), ex);
256  }
257  } else {
258  // for single-user cases need to verify connection to local SOLR service
259  try {
260  if (!server.isRunning()) {
261  throw new IngestModuleException(Bundle.KeywordSearchIngestModule_init_tryStopSolrMsg(Bundle.KeywordSearchIngestModule_init_badInitMsg()));
262  }
263  } catch (KeywordSearchModuleException ex) {
264  //this means Solr is not properly initialized
265  throw new IngestModuleException(Bundle.KeywordSearchIngestModule_init_tryStopSolrMsg(Bundle.KeywordSearchIngestModule_init_badInitMsg()), ex);
266  }
267  try {
268  // make an actual query to verify that server is responding
269  // we had cases where getStatus was OK, but the connection resulted in a 404
270  server.queryNumIndexedDocuments();
272  throw new IngestModuleException(Bundle.KeywordSearchIngestModule_init_exception_errConnToSolr_msg(ex.getMessage()), ex);
273  }
274 
275  // check if this job has any searchable keywords
276  List<KeywordList> keywordLists = XmlKeywordSearchList.getCurrent().getListsL();
277  boolean hasKeywordsForSearch = false;
278  for (KeywordList keywordList : keywordLists) {
279  if (settings.keywordListIsEnabled(keywordList.getName()) && !keywordList.getKeywords().isEmpty()) {
280  hasKeywordsForSearch = true;
281  break;
282  }
283  }
284  if (!hasKeywordsForSearch) {
285  services.postMessage(IngestMessage.createWarningMessage(KeywordSearchModuleFactory.getModuleName(), NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.init.noKwInLstMsg"),
286  NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.init.onlyIdxKwSkipMsg")));
287  }
288  }
289  }
290 
291  StringsConfig stringsConfig = new StringsConfig();
292  Map<String, String> stringsOptions = KeywordSearchSettings.getStringExtractOptions();
293  stringsConfig.setExtractUTF8(Boolean.parseBoolean(stringsOptions.get(StringsExtractOptions.EXTRACT_UTF8.toString())));
294  stringsConfig.setExtractUTF16(Boolean.parseBoolean(stringsOptions.get(StringsExtractOptions.EXTRACT_UTF16.toString())));
295  stringsConfig.setLanguageScripts(KeywordSearchSettings.getStringExtractScripts());
296 
297  stringsExtractionContext = Lookups.fixed(stringsConfig);
298 
299  indexer = new Indexer();
300  initialized = true;
301  }
302 
303  @Override
304  public ProcessResult process(AbstractFile abstractFile) {
305  if (initialized == false) //error initializing indexing/Solr
306  {
307  logger.log(Level.SEVERE, "Skipping processing, module not initialized, file: {0}", abstractFile.getName()); //NON-NLS
308  putIngestStatus(jobId, abstractFile.getId(), IngestStatus.SKIPPED_ERROR_INDEXING);
309  return ProcessResult.OK;
310  }
311 
312  if (abstractFile.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR)) {
313  //skip indexing of virtual dirs (no content, no real name) - will index children files
314  return ProcessResult.OK;
315  }
316 
317  if (KeywordSearchSettings.getSkipKnown() && abstractFile.getKnown().equals(FileKnown.KNOWN)) {
318  //index meta-data only
319  if (context.fileIngestIsCancelled()) {
320  return ProcessResult.OK;
321  }
322  indexer.indexFile(abstractFile, false);
323  return ProcessResult.OK;
324  }
325 
326  //index the file and content (if the content is supported)
327  if (context.fileIngestIsCancelled()) {
328  return ProcessResult.OK;
329  }
330  indexer.indexFile(abstractFile, true);
331 
332  // Start searching if it hasn't started already
333  if (!startedSearching) {
334  if (context.fileIngestIsCancelled()) {
335  return ProcessResult.OK;
336  }
337  List<String> keywordListNames = settings.getNamesOfEnabledKeyWordLists();
338  IngestSearchRunner.getInstance().startJob(context, keywordListNames);
339  startedSearching = true;
340  }
341 
342  return ProcessResult.OK;
343  }
344 
349  @Override
350  public void shutDown() {
351  logger.log(Level.INFO, "Keyword search ingest module instance {0} shutting down", instanceNum); //NON-NLS
352 
353  if ((initialized == false) || (context == null)) {
354  return;
355  }
356 
357  if (context.fileIngestIsCancelled()) {
358  logger.log(Level.INFO, "Keyword search ingest module instance {0} stopping search job due to ingest cancellation", instanceNum); //NON-NLS
359  IngestSearchRunner.getInstance().stopJob(jobId);
360  cleanup();
361  return;
362  }
363 
364  // Remove from the search list and trigger final commit and final search
365  IngestSearchRunner.getInstance().endJob(jobId);
366 
367  // We only need to post the summary msg from the last module per job
368  if (refCounter.decrementAndGet(jobId) == 0) {
369  try {
370  final int numIndexedFiles = KeywordSearch.getServer().queryNumIndexedFiles();
371  logger.log(Level.INFO, "Indexed files count: {0}", numIndexedFiles); //NON-NLS
372  final int numIndexedChunks = KeywordSearch.getServer().queryNumIndexedChunks();
373  logger.log(Level.INFO, "Indexed file chunks count: {0}", numIndexedChunks); //NON-NLS
375  logger.log(Level.SEVERE, "Error executing Solr queries to check number of indexed files and file chunks", ex); //NON-NLS
376  }
377  postIndexSummary();
378  synchronized (ingestStatus) {
379  ingestStatus.remove(jobId);
380  }
381  }
382 
383  cleanup();
384  }
385 
389  private void cleanup() {
390  stringsExtractionContext = null;
391  initialized = false;
392  }
393 
397  private void postIndexSummary() {
398  int text_ingested = 0;
399  int metadata_ingested = 0;
400  int strings_ingested = 0;
401  int error_text = 0;
402  int error_index = 0;
403  int error_io = 0;
404 
405  synchronized (ingestStatus) {
406  Map<Long, IngestStatus> ingestStatusForJob = ingestStatus.get(jobId);
407  if (ingestStatusForJob == null) {
408  return;
409  }
410  for (IngestStatus s : ingestStatusForJob.values()) {
411  switch (s) {
412  case TEXT_INGESTED:
413  text_ingested++;
414  break;
415  case METADATA_INGESTED:
416  metadata_ingested++;
417  break;
418  case STRINGS_INGESTED:
419  strings_ingested++;
420  break;
421  case SKIPPED_ERROR_TEXTEXTRACT:
422  error_text++;
423  break;
424  case SKIPPED_ERROR_INDEXING:
425  error_index++;
426  break;
427  case SKIPPED_ERROR_IO:
428  error_io++;
429  break;
430  default:
431  ;
432  }
433  }
434  }
435 
436  StringBuilder msg = new StringBuilder();
437  msg.append("<table border=0><tr><td>").append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.postIndexSummary.knowFileHeaderLbl")).append("</td><td>").append(text_ingested).append("</td></tr>"); //NON-NLS
438  msg.append("<tr><td>").append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.postIndexSummary.fileGenStringsHead")).append("</td><td>").append(strings_ingested).append("</td></tr>"); //NON-NLS
439  msg.append("<tr><td>").append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.postIndexSummary.mdOnlyLbl")).append("</td><td>").append(metadata_ingested).append("</td></tr>"); //NON-NLS
440  msg.append("<tr><td>").append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.postIndexSummary.idxErrLbl")).append("</td><td>").append(error_index).append("</td></tr>"); //NON-NLS
441  msg.append("<tr><td>").append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.postIndexSummary.errTxtLbl")).append("</td><td>").append(error_text).append("</td></tr>"); //NON-NLS
442  msg.append("<tr><td>").append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.postIndexSummary.errIoLbl")).append("</td><td>").append(error_io).append("</td></tr>"); //NON-NLS
443  msg.append("</table>"); //NON-NLS
444  String indexStats = msg.toString();
445  logger.log(Level.INFO, "Keyword Indexing Completed: {0}", indexStats); //NON-NLS
446  services.postMessage(IngestMessage.createMessage(MessageType.INFO, KeywordSearchModuleFactory.getModuleName(), NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.postIndexSummary.kwIdxResultsLbl"), indexStats));
447  if (error_index > 0) {
448  MessageNotifyUtil.Notify.error(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.postIndexSummary.kwIdxErrsTitle"),
449  NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.postIndexSummary.kwIdxErrMsgFiles", error_index));
450  } else if (error_io + error_text > 0) {
451  MessageNotifyUtil.Notify.warn(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.postIndexSummary.kwIdxWarnMsgTitle"),
452  NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.postIndexSummary.idxErrReadFilesMsg"));
453  }
454  }
455 
460  private class Indexer {
461 
462  private final Logger logger = Logger.getLogger(Indexer.class.getName());
463 
477  private boolean extractTextAndIndex(AbstractFile aFile, String detectedFormat) throws IngesterException {
478  ImageConfig imageConfig = new ImageConfig();
479  imageConfig.setOCREnabled(KeywordSearchSettings.getOcrOption());
480  Lookup extractionContext = Lookups.fixed(imageConfig);
481 
482  try {
483  Reader specializedReader = TextReaders.getReader(aFile,extractionContext);
484  //divide into chunks and index
485  return Ingester.getDefault().indexText(specializedReader,aFile.getId(),aFile.getName(), aFile, context);
486  } catch (TextReaders.NoTextReaderFound ex) {
487  //No text extractor found... run the default instead
488  return false;
489  }
490  }
491 
500  private boolean extractStringsAndIndex(AbstractFile aFile) {
501  try {
502  if (context.fileIngestIsCancelled()) {
503  return true;
504  }
505  Reader stringsReader = TextReaders.getStringsReader(aFile, stringsExtractionContext);
506  if (Ingester.getDefault().indexText(stringsReader,aFile.getId(),aFile.getName(), aFile, KeywordSearchIngestModule.this.context)) {
507  putIngestStatus(jobId, aFile.getId(), IngestStatus.STRINGS_INGESTED);
508  return true;
509  } else {
510  logger.log(Level.WARNING, "Failed to extract strings and ingest, file ''{0}'' (id: {1}).", new Object[]{aFile.getName(), aFile.getId()}); //NON-NLS
511  putIngestStatus(jobId, aFile.getId(), IngestStatus.SKIPPED_ERROR_TEXTEXTRACT);
512  return false;
513  }
514  } catch (IngesterException ex) {
515  logger.log(Level.WARNING, "Failed to extract strings and ingest, file '" + aFile.getName() + "' (id: " + aFile.getId() + ").", ex); //NON-NLS
516  putIngestStatus(jobId, aFile.getId(), IngestStatus.SKIPPED_ERROR_INDEXING);
517  return false;
518  }
519  }
520 
528  private void indexFile(AbstractFile aFile, boolean indexContent) {
529  //logger.log(Level.INFO, "Processing AbstractFile: " + abstractFile.getName());
530 
531  TskData.TSK_DB_FILES_TYPE_ENUM aType = aFile.getType();
532 
533  // unallocated and unused blocks can only have strings extracted from them.
534  if ((aType.equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) || aType.equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS))) {
535  if (context.fileIngestIsCancelled()) {
536  return;
537  }
538  extractStringsAndIndex(aFile);
539  return;
540  }
541 
542  final long size = aFile.getSize();
543  //if not to index content, or a dir, or 0 content, index meta data only
544 
545  if ((indexContent == false || aFile.isDir() || size == 0)) {
546  try {
547  if (context.fileIngestIsCancelled()) {
548  return;
549  }
550  ingester.indexMetaDataOnly(aFile);
551  putIngestStatus(jobId, aFile.getId(), IngestStatus.METADATA_INGESTED);
552  } catch (IngesterException ex) {
553  putIngestStatus(jobId, aFile.getId(), IngestStatus.SKIPPED_ERROR_INDEXING);
554  logger.log(Level.WARNING, "Unable to index meta-data for file: " + aFile.getId(), ex); //NON-NLS
555  }
556  return;
557  }
558 
559  if (context.fileIngestIsCancelled()) {
560  return;
561  }
562  String fileType = fileTypeDetector.getMIMEType(aFile);
563 
564  // we skip archive formats that are opened by the archive module.
565  // @@@ We could have a check here to see if the archive module was enabled though...
566  if (ARCHIVE_MIME_TYPES.contains(fileType)) {
567  try {
568  if (context.fileIngestIsCancelled()) {
569  return;
570  }
571  ingester.indexMetaDataOnly(aFile);
572  putIngestStatus(jobId, aFile.getId(), IngestStatus.METADATA_INGESTED);
573  } catch (IngesterException ex) {
574  putIngestStatus(jobId, aFile.getId(), IngestStatus.SKIPPED_ERROR_INDEXING);
575  logger.log(Level.WARNING, "Unable to index meta-data for file: " + aFile.getId(), ex); //NON-NLS
576  }
577  return;
578  }
579 
580  boolean wasTextAdded = false;
581 
582  //extract text with one of the extractors, divide into chunks and index with Solr
583  try {
584  //logger.log(Level.INFO, "indexing: " + aFile.getName());
585  if (context.fileIngestIsCancelled()) {
586  return;
587  }
588  if (fileType.equals("application/octet-stream")) {
589  extractStringsAndIndex(aFile);
590  return;
591  }
592  if (!extractTextAndIndex(aFile, fileType)) {
593  // Text extractor not found for file. Extract string only.
594  putIngestStatus(jobId, aFile.getId(), IngestStatus.SKIPPED_ERROR_TEXTEXTRACT);
595  } else {
596  putIngestStatus(jobId, aFile.getId(), IngestStatus.TEXT_INGESTED);
597  wasTextAdded = true;
598  }
599 
600  } catch (IngesterException e) {
601  logger.log(Level.INFO, "Could not extract text with Tika, " + aFile.getId() + ", " //NON-NLS
602  + aFile.getName(), e);
603  putIngestStatus(jobId, aFile.getId(), IngestStatus.SKIPPED_ERROR_INDEXING);
604  } catch (Exception e) {
605  logger.log(Level.WARNING, "Error extracting text with Tika, " + aFile.getId() + ", " //NON-NLS
606  + aFile.getName(), e);
607  putIngestStatus(jobId, aFile.getId(), IngestStatus.SKIPPED_ERROR_TEXTEXTRACT);
608  }
609 
610  if ((wasTextAdded == false) && (aFile.getNameExtension().equalsIgnoreCase("txt") && !(aFile.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.CARVED)))) {
611  //Carved Files should be the only type of unallocated files capable of a txt extension and
612  //should be ignored by the TextFileExtractor because they may contain more than one text encoding
613  try {
614  TextFileExtractor textFileExtractor = new TextFileExtractor();
615  Reader textReader = textFileExtractor.getReader(aFile);
616  if (Ingester.getDefault().indexText(textReader, aFile.getId(), aFile.getName(), aFile, context)) {
617  putIngestStatus(jobId, aFile.getId(), IngestStatus.TEXT_INGESTED);
618  wasTextAdded = true;
619  }
620  } catch (IngesterException | TextFileExtractorException ex) {
621  logger.log(Level.WARNING, "Unable to index as unicode", ex);
622  }
623  }
624 
625  // if it wasn't supported or had an error, default to strings
626  if (wasTextAdded == false) {
627  extractStringsAndIndex(aFile);
628  }
629  }
630  }
631 }
static IndexingServerProperties getMultiUserServerProperties(String caseDirectory)
Definition: Server.java:852
boolean extractTextAndIndex(AbstractFile aFile, String detectedFormat)
static Reader getStringsReader(Content content, Lookup context)
static IngestMessage createMessage(MessageType messageType, String source, String subject, String detailsHtml)
static Reader getReader(Content content, Lookup context)
void postMessage(final IngestMessage message)
static void putIngestStatus(long ingestJobId, long fileId, IngestStatus status)
static void error(String title, String message)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
static IngestMessage createWarningMessage(String source, String subject, String detailsHtml)
static void warn(String title, String message)
static synchronized IngestServices getInstance()
STRINGS_INGESTED
Text was extracted by knowing file type and text_ingested.

Copyright © 2012-2018 Basis Technology. Generated on: Tue Dec 18 2018
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.